aboutsummaryrefslogtreecommitdiff
path: root/target/loongarch/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/loongarch/cpu.c')
-rw-r--r--target/loongarch/cpu.c336
1 files changed, 255 insertions, 81 deletions
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 270f711..abad84c 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -10,26 +10,29 @@
#include "qemu/qemu-print.h"
#include "qapi/error.h"
#include "qemu/module.h"
-#include "sysemu/qtest.h"
-#include "sysemu/tcg.h"
-#include "sysemu/kvm.h"
+#include "system/qtest.h"
+#include "system/tcg.h"
+#include "system/kvm.h"
#include "kvm/kvm_loongarch.h"
-#include "exec/exec-all.h"
+#include "hw/qdev-properties.h"
+#include "exec/translation-block.h"
#include "cpu.h"
#include "internals.h"
#include "fpu/softfloat-helpers.h"
-#include "cpu-csr.h"
+#include "csr.h"
#ifndef CONFIG_USER_ONLY
-#include "sysemu/reset.h"
+#include "system/reset.h"
#endif
#include "vec.h"
#ifdef CONFIG_KVM
#include <linux/kvm.h>
#endif
#ifdef CONFIG_TCG
-#include "exec/cpu_ldst.h"
+#include "accel/tcg/cpu-ldst.h"
+#include "accel/tcg/cpu-ops.h"
#include "tcg/tcg.h"
#endif
+#include "tcg/tcg_loongarch.h"
const char * const regnames[32] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -331,8 +334,28 @@ static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
}
return false;
}
+
+static vaddr loongarch_pointer_wrap(CPUState *cs, int mmu_idx,
+ vaddr result, vaddr base)
+{
+ return is_va32(cpu_env(cs)) ? (uint32_t)result : result;
+}
#endif
+static TCGTBCPUState loongarch_get_tb_cpu_state(CPUState *cs)
+{
+ CPULoongArchState *env = cpu_env(cs);
+ uint32_t flags;
+
+ flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
+ flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
+ flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
+ flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE;
+ flags |= is_va32(env) * HW_FLAGS_VA32;
+
+ return (TCGTBCPUState){ .pc = env->pc, .flags = flags };
+}
+
static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
@@ -348,11 +371,9 @@ static void loongarch_restore_state_to_opc(CPUState *cs,
}
#endif /* CONFIG_TCG */
+#ifndef CONFIG_USER_ONLY
static bool loongarch_cpu_has_work(CPUState *cs)
{
-#ifdef CONFIG_USER_ONLY
- return true;
-#else
bool has_work = false;
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
@@ -361,8 +382,8 @@ static bool loongarch_cpu_has_work(CPUState *cs)
}
return has_work;
-#endif
}
+#endif /* !CONFIG_USER_ONLY */
static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
{
@@ -374,10 +395,38 @@ static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
return MMU_DA_IDX;
}
+static void loongarch_la464_init_csr(Object *obj)
+{
+#ifndef CONFIG_USER_ONLY
+ static bool initialized;
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ CPULoongArchState *env = &cpu->env;
+ int i, num;
+
+ if (!initialized) {
+ initialized = true;
+ num = FIELD_EX64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM);
+ for (i = num; i < 16; i++) {
+ set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED);
+ }
+ set_csr_flag(LOONGARCH_CSR_IMPCTL1, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_IMPCTL2, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRCTL, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRINFO1, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRINFO2, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRENTRY, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRERA, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRSAVE, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_CTAG, CSRFL_UNUSED);
+ }
+#endif
+}
+
static void loongarch_la464_initfn(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
CPULoongArchState *env = &cpu->env;
+ uint32_t data = 0, field;
int i;
for (i = 0; i < 21; i++) {
@@ -387,18 +436,23 @@ static void loongarch_la464_initfn(Object *obj)
cpu->dtb_compatible = "loongarch,Loongson-3A5000";
env->cpucfg[0] = 0x14c010; /* PRID */
- uint32_t data = 0;
data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
- data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
+ if (kvm_enabled()) {
+ /* GPA address width of VM is 47, field value is 47 - 1 */
+ field = 0x2e;
+ } else {
+ field = 0x2f; /* 48 bit - 1 */
+ }
+ data = FIELD_DP32(data, CPUCFG1, PALEN, field);
data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
data = FIELD_DP32(data, CPUCFG1, UAL, 1);
data = FIELD_DP32(data, CPUCFG1, RI, 1);
data = FIELD_DP32(data, CPUCFG1, EP, 1);
data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
data = FIELD_DP32(data, CPUCFG1, HP, 1);
- data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
+ data = FIELD_DP32(data, CPUCFG1, CRC, 1);
env->cpucfg[1] = data;
data = 0;
@@ -457,6 +511,19 @@ static void loongarch_la464_initfn(Object *obj)
env->cpucfg[20] = data;
env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
+
+ env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8);
+ env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f);
+ env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7);
+
+ env->CSR_PRCFG2 = 0x3ffff000;
+
+ 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);
+ env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
+ env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
+
+ loongarch_la464_init_csr(obj);
loongarch_cpu_post_init(obj);
}
@@ -464,7 +531,7 @@ static void loongarch_la132_initfn(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
CPULoongArchState *env = &cpu->env;
-
+ uint32_t data = 0;
int i;
for (i = 0; i < 21; i++) {
@@ -474,7 +541,6 @@ static void loongarch_la132_initfn(Object *obj)
cpu->dtb_compatible = "loongarch,Loongson-1C103";
env->cpucfg[0] = 0x148042; /* PRID */
- uint32_t data = 0;
data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
@@ -485,7 +551,7 @@ static void loongarch_la132_initfn(Object *obj)
data = FIELD_DP32(data, CPUCFG1, EP, 0);
data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
data = FIELD_DP32(data, CPUCFG1, HP, 1);
- data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
+ data = FIELD_DP32(data, CPUCFG1, CRC, 1);
env->cpucfg[1] = data;
}
@@ -497,6 +563,7 @@ static void loongarch_max_initfn(Object *obj)
static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
{
+ uint8_t tlb_ps;
CPUState *cs = CPU(obj);
LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
CPULoongArchState *env = cpu_env(cs);
@@ -511,13 +578,13 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
env->fcsr0 = 0x0;
int n;
- /* Set csr registers value after reset */
+ /* Set csr registers value after reset, see the manual 6.4. */
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0);
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0);
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1);
env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0);
- env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATF, 1);
- env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 1);
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATF, 0);
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 0);
env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, FPE, 0);
env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, SXE, 0);
@@ -537,12 +604,25 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
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);
- env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
- env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
-
+ /*
+ * Workaround for edk2-stable202408, CSR PGD register is set only if
+ * its value is equal to zero for boot cpu, it causes reboot issue.
+ *
+ * Here clear CSR registers relative with TLB.
+ */
+ env->CSR_PGDH = 0;
+ env->CSR_PGDL = 0;
+ env->CSR_PWCH = 0;
+ env->CSR_EENTRY = 0;
+ env->CSR_TLBRENTRY = 0;
+ env->CSR_MERRENTRY = 0;
+ /* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */
+ if (env->CSR_PRCFG2 == 0) {
+ env->CSR_PRCFG2 = 0x3fffff000;
+ }
+ tlb_ps = ctz32(env->CSR_PRCFG2);
+ env->CSR_STLBPS = FIELD_DP64(env->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps);
+ env->CSR_PWCL = FIELD_DP64(env->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps);
for (n = 0; n < 4; n++) {
env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0);
env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0);
@@ -556,7 +636,7 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
memset(env->tlb, 0, sizeof(env->tlb));
#endif
if (kvm_enabled()) {
- kvm_arch_reset_vcpu(env);
+ kvm_arch_reset_vcpu(cs);
}
#endif
@@ -568,6 +648,7 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
{
+ info->endian = BFD_ENDIAN_LITTLE;
info->print_insn = print_insn_loongarch;
}
@@ -585,70 +666,111 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
loongarch_cpu_register_gdb_regs_for_features(cs);
- cpu_reset(cs);
qemu_init_vcpu(cs);
+ cpu_reset(cs);
lacc->parent_realize(dev, errp);
}
-static bool loongarch_get_lsx(Object *obj, Error **errp)
+static void loongarch_cpu_unrealizefn(DeviceState *dev)
{
- LoongArchCPU *cpu = LOONGARCH_CPU(obj);
- bool ret;
+ LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
- if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
- ret = true;
- } else {
- ret = false;
- }
- return ret;
+#ifndef CONFIG_USER_ONLY
+ cpu_remove_sync(CPU(dev));
+#endif
+
+ lacc->parent_unrealize(dev);
+}
+
+static bool loongarch_get_lsx(Object *obj, Error **errp)
+{
+ return LOONGARCH_CPU(obj)->lsx != ON_OFF_AUTO_OFF;
}
static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ uint32_t val;
+
+ cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
+ if (cpu->lsx == ON_OFF_AUTO_OFF) {
+ cpu->lasx = ON_OFF_AUTO_OFF;
+ if (cpu->lasx == ON_OFF_AUTO_ON) {
+ error_setg(errp, "Failed to disable LSX since LASX is enabled");
+ return;
+ }
+ }
+
+ if (kvm_enabled()) {
+ /* kvm feature detection in function kvm_arch_init_vcpu */
+ return;
+ }
- if (value) {
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
+ /* LSX feature detection in TCG mode */
+ val = cpu->env.cpucfg[2];
+ if (cpu->lsx == ON_OFF_AUTO_ON) {
+ if (FIELD_EX32(val, CPUCFG2, LSX) == 0) {
+ error_setg(errp, "Failed to enable LSX in TCG mode");
+ return;
+ }
} else {
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0);
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, 0);
+ val = cpu->env.cpucfg[2];
}
+
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value);
}
static bool loongarch_get_lasx(Object *obj, Error **errp)
{
- LoongArchCPU *cpu = LOONGARCH_CPU(obj);
- bool ret;
-
- if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) {
- ret = true;
- } else {
- ret = false;
- }
- return ret;
+ return LOONGARCH_CPU(obj)->lasx != ON_OFF_AUTO_OFF;
}
static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ uint32_t val;
- if (value) {
- if (!FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
- }
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 1);
- } else {
- cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
+ cpu->lasx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
+ if ((cpu->lsx == ON_OFF_AUTO_OFF) && (cpu->lasx == ON_OFF_AUTO_ON)) {
+ error_setg(errp, "Failed to enable LASX since lSX is disabled");
+ return;
+ }
+
+ if (kvm_enabled()) {
+ /* kvm feature detection in function kvm_arch_init_vcpu */
+ return;
}
+
+ /* LASX feature detection in TCG mode */
+ val = cpu->env.cpucfg[2];
+ if (cpu->lasx == ON_OFF_AUTO_ON) {
+ if (FIELD_EX32(val, CPUCFG2, LASX) == 0) {
+ error_setg(errp, "Failed to enable LASX in TCG mode");
+ return;
+ }
+ }
+
+ cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value);
}
void loongarch_cpu_post_init(Object *obj)
{
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+ cpu->lbt = ON_OFF_AUTO_OFF;
+ cpu->pmu = ON_OFF_AUTO_OFF;
+ cpu->lsx = ON_OFF_AUTO_AUTO;
+ cpu->lasx = ON_OFF_AUTO_AUTO;
object_property_add_bool(obj, "lsx", loongarch_get_lsx,
loongarch_set_lsx);
object_property_add_bool(obj, "lasx", loongarch_get_lasx,
loongarch_set_lasx);
+ /* lbt is enabled only in kvm mode, not supported in tcg mode */
+ if (kvm_enabled()) {
+ kvm_loongarch_cpu_post_init(cpu);
+ }
}
static void loongarch_cpu_init(Object *obj)
@@ -678,7 +800,55 @@ static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
return oc;
}
-void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
+static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f)
+{
+#ifndef CONFIG_USER_ONLY
+ CPULoongArchState *env = cpu_env(cs);
+ CSRInfo *csr_info;
+ int64_t *addr;
+ int i, j, len, col = 0;
+
+ qemu_fprintf(f, "\n");
+
+ /* Dump all generic CSR register */
+ for (i = 0; i < LOONGARCH_CSR_DBG; i++) {
+ csr_info = get_csr(i);
+ if (!csr_info || (csr_info->flags & CSRFL_UNUSED)) {
+ if (i == (col + 3)) {
+ qemu_fprintf(f, "\n");
+ }
+
+ continue;
+ }
+
+ if ((i > (col + 3)) || (i == col)) {
+ col = i & ~3;
+ qemu_fprintf(f, " CSR%03d:", col);
+ }
+
+ addr = (void *)env + csr_info->offset;
+ qemu_fprintf(f, " %s ", csr_info->name);
+ len = strlen(csr_info->name);
+ for (; len < 6; len++) {
+ qemu_fprintf(f, " ");
+ }
+
+ qemu_fprintf(f, "%" PRIx64, *addr);
+ j = find_last_bit((void *)addr, BITS_PER_LONG) & (BITS_PER_LONG - 1);
+ len += j / 4 + 1;
+ for (; len < 22; len++) {
+ qemu_fprintf(f, " ");
+ }
+
+ if (i == (col + 3)) {
+ qemu_fprintf(f, "\n");
+ }
+ }
+ qemu_fprintf(f, "\n");
+#endif
+}
+
+static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
CPULoongArchState *env = cpu_env(cs);
int i;
@@ -697,22 +867,8 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
}
- qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
- qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
- qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
- qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
- qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
- qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
- qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
- qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
- qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
- " PRCFG3=%016" PRIx64 "\n",
- env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
- qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
- qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
- qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
- qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG);
- qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL);
+ /* csr */
+ loongarch_cpu_dump_csr(cs, f);
/* fpr */
if (flags & CPU_DUMP_FPU) {
@@ -726,16 +882,23 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
#ifdef CONFIG_TCG
-#include "hw/core/tcg-cpu-ops.h"
-
static const TCGCPUOps loongarch_tcg_ops = {
+ .guest_default_memory_order = 0,
+ .mttcg_supported = true,
+
.initialize = loongarch_translate_init,
+ .translate_code = loongarch_translate_code,
+ .get_tb_cpu_state = loongarch_get_tb_cpu_state,
.synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
.restore_state_to_opc = loongarch_restore_state_to_opc,
+ .mmu_index = loongarch_cpu_mmu_index,
#ifndef CONFIG_USER_ONLY
.tlb_fill = loongarch_cpu_tlb_fill,
+ .pointer_wrap = loongarch_pointer_wrap,
.cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
+ .cpu_exec_halt = loongarch_cpu_has_work,
+ .cpu_exec_reset = cpu_reset,
.do_interrupt = loongarch_cpu_do_interrupt,
.do_transaction_failed = loongarch_cpu_do_transaction_failed,
#endif
@@ -746,6 +909,8 @@ static const TCGCPUOps loongarch_tcg_ops = {
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps loongarch_sysemu_ops = {
+ .has_work = loongarch_cpu_has_work,
+ .write_elf64_note = loongarch_cpu_write_elf64_note,
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
};
@@ -757,21 +922,29 @@ static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
}
#endif
-static void loongarch_cpu_class_init(ObjectClass *c, void *data)
+static const Property loongarch_cpu_properties[] = {
+ DEFINE_PROP_INT32("socket-id", LoongArchCPU, socket_id, 0),
+ DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, 0),
+ DEFINE_PROP_INT32("thread-id", LoongArchCPU, thread_id, 0),
+ DEFINE_PROP_INT32("node-id", LoongArchCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
+};
+
+static void loongarch_cpu_class_init(ObjectClass *c, const void *data)
{
LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
CPUClass *cc = CPU_CLASS(c);
DeviceClass *dc = DEVICE_CLASS(c);
ResettableClass *rc = RESETTABLE_CLASS(c);
+ device_class_set_props(dc, loongarch_cpu_properties);
device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
&lacc->parent_realize);
+ device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
+ &lacc->parent_unrealize);
resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL,
&lacc->parent_phases);
cc->class_by_name = loongarch_cpu_class_by_name;
- cc->has_work = loongarch_cpu_has_work;
- cc->mmu_index = loongarch_cpu_mmu_index;
cc->dump_state = loongarch_cpu_dump_state;
cc->set_pc = loongarch_cpu_set_pc;
cc->get_pc = loongarch_cpu_get_pc;
@@ -788,6 +961,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
#ifdef CONFIG_TCG
cc->tcg_ops = &loongarch_tcg_ops;
#endif
+ dc->user_creatable = true;
}
static const gchar *loongarch32_gdb_arch_name(CPUState *cs)
@@ -795,7 +969,7 @@ static const gchar *loongarch32_gdb_arch_name(CPUState *cs)
return "loongarch32";
}
-static void loongarch32_cpu_class_init(ObjectClass *c, void *data)
+static void loongarch32_cpu_class_init(ObjectClass *c, const void *data)
{
CPUClass *cc = CPU_CLASS(c);
@@ -808,7 +982,7 @@ static const gchar *loongarch64_gdb_arch_name(CPUState *cs)
return "loongarch64";
}
-static void loongarch64_cpu_class_init(ObjectClass *c, void *data)
+static void loongarch64_cpu_class_init(ObjectClass *c, const void *data)
{
CPUClass *cc = CPU_CLASS(c);