xref: /openbmc/qemu/target/loongarch/cpu.c (revision ee057a9f2976e1fb2f58e07e86b410f38bf04ac6)
1228021f0SSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
2228021f0SSong Gao /*
3228021f0SSong Gao  * QEMU LoongArch CPU
4228021f0SSong Gao  *
5228021f0SSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
6228021f0SSong Gao  */
7228021f0SSong Gao 
8228021f0SSong Gao #include "qemu/osdep.h"
9228021f0SSong Gao #include "qemu/log.h"
10228021f0SSong Gao #include "qemu/qemu-print.h"
11228021f0SSong Gao #include "qapi/error.h"
12228021f0SSong Gao #include "qemu/module.h"
13228021f0SSong Gao #include "sysemu/qtest.h"
142d45085aSTianrui Zhao #include "sysemu/tcg.h"
158dcbad51STianrui Zhao #include "sysemu/kvm.h"
168dcbad51STianrui Zhao #include "kvm/kvm_loongarch.h"
17228021f0SSong Gao #include "exec/exec-all.h"
18228021f0SSong Gao #include "cpu.h"
19228021f0SSong Gao #include "internals.h"
20228021f0SSong Gao #include "fpu/softfloat-helpers.h"
21398cecb9SXiaojuan Yang #include "cpu-csr.h"
22c0f6cd9fSPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
23f84a2aacSXiaojuan Yang #include "sysemu/reset.h"
24c0f6cd9fSPhilippe Mathieu-Daudé #endif
25008a3b16SSong Gao #include "vec.h"
268dcbad51STianrui Zhao #ifdef CONFIG_KVM
278dcbad51STianrui Zhao #include <linux/kvm.h>
288dcbad51STianrui Zhao #endif
292d45085aSTianrui Zhao #ifdef CONFIG_TCG
302d45085aSTianrui Zhao #include "exec/cpu_ldst.h"
312d45085aSTianrui Zhao #include "tcg/tcg.h"
322d45085aSTianrui Zhao #endif
33228021f0SSong Gao 
34228021f0SSong Gao const char * const regnames[32] = {
35228021f0SSong Gao     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
36228021f0SSong Gao     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
37228021f0SSong Gao     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
38228021f0SSong Gao     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
39228021f0SSong Gao };
40228021f0SSong Gao 
41228021f0SSong Gao const char * const fregnames[32] = {
42228021f0SSong Gao     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
43228021f0SSong Gao     "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
44228021f0SSong Gao     "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
45228021f0SSong Gao     "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
46228021f0SSong Gao };
47228021f0SSong Gao 
481590154eSSong Gao struct TypeExcp {
491590154eSSong Gao     int32_t exccode;
501590154eSSong Gao     const char * const name;
511590154eSSong Gao };
521590154eSSong Gao 
531590154eSSong Gao static const struct TypeExcp excp_names[] = {
541590154eSSong Gao     {EXCCODE_INT, "Interrupt"},
551590154eSSong Gao     {EXCCODE_PIL, "Page invalid exception for load"},
561590154eSSong Gao     {EXCCODE_PIS, "Page invalid exception for store"},
571590154eSSong Gao     {EXCCODE_PIF, "Page invalid exception for fetch"},
581590154eSSong Gao     {EXCCODE_PME, "Page modified exception"},
591590154eSSong Gao     {EXCCODE_PNR, "Page Not Readable exception"},
601590154eSSong Gao     {EXCCODE_PNX, "Page Not Executable exception"},
611590154eSSong Gao     {EXCCODE_PPI, "Page Privilege error"},
621590154eSSong Gao     {EXCCODE_ADEF, "Address error for instruction fetch"},
631590154eSSong Gao     {EXCCODE_ADEM, "Address error for Memory access"},
641590154eSSong Gao     {EXCCODE_SYS, "Syscall"},
651590154eSSong Gao     {EXCCODE_BRK, "Break"},
661590154eSSong Gao     {EXCCODE_INE, "Instruction Non-Existent"},
671590154eSSong Gao     {EXCCODE_IPE, "Instruction privilege error"},
681590154eSSong Gao     {EXCCODE_FPD, "Floating Point Disabled"},
691590154eSSong Gao     {EXCCODE_FPE, "Floating Point Exception"},
701590154eSSong Gao     {EXCCODE_DBP, "Debug breakpoint"},
711590154eSSong Gao     {EXCCODE_BCE, "Bound Check Exception"},
721590154eSSong Gao     {EXCCODE_SXD, "128 bit vector instructions Disable exception"},
731590154eSSong Gao     {EXCCODE_ASXD, "256 bit vector instructions Disable exception"},
741590154eSSong Gao     {EXCP_HLT, "EXCP_HLT"},
75228021f0SSong Gao };
76228021f0SSong Gao 
loongarch_exception_name(int32_t exception)77228021f0SSong Gao const char *loongarch_exception_name(int32_t exception)
78228021f0SSong Gao {
791590154eSSong Gao     int i;
801590154eSSong Gao 
811590154eSSong Gao     for (i = 0; i < ARRAY_SIZE(excp_names); i++) {
821590154eSSong Gao         if (excp_names[i].exccode == exception) {
831590154eSSong Gao             return excp_names[i].name;
841590154eSSong Gao         }
851590154eSSong Gao     }
861590154eSSong Gao     return "Unknown";
87228021f0SSong Gao }
88228021f0SSong Gao 
do_raise_exception(CPULoongArchState * env,uint32_t exception,uintptr_t pc)89228021f0SSong Gao void G_NORETURN do_raise_exception(CPULoongArchState *env,
90228021f0SSong Gao                                    uint32_t exception,
91228021f0SSong Gao                                    uintptr_t pc)
92228021f0SSong Gao {
93228021f0SSong Gao     CPUState *cs = env_cpu(env);
94228021f0SSong Gao 
950cbb322fSMichael Tokarev     qemu_log_mask(CPU_LOG_INT, "%s: exception: %d (%s)\n",
96228021f0SSong Gao                   __func__,
97228021f0SSong Gao                   exception,
98228021f0SSong Gao                   loongarch_exception_name(exception));
99228021f0SSong Gao     cs->exception_index = exception;
100228021f0SSong Gao 
101228021f0SSong Gao     cpu_loop_exit_restore(cs, pc);
102228021f0SSong Gao }
103228021f0SSong Gao 
loongarch_cpu_set_pc(CPUState * cs,vaddr value)104228021f0SSong Gao static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
105228021f0SSong Gao {
106f3b603b9SPhilippe Mathieu-Daudé     set_pc(cpu_env(cs), value);
107228021f0SSong Gao }
108228021f0SSong Gao 
loongarch_cpu_get_pc(CPUState * cs)109e4fdf9dfSRichard Henderson static vaddr loongarch_cpu_get_pc(CPUState *cs)
110e4fdf9dfSRichard Henderson {
111f3b603b9SPhilippe Mathieu-Daudé     return cpu_env(cs)->pc;
112e4fdf9dfSRichard Henderson }
113e4fdf9dfSRichard Henderson 
1140093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
115a8a506c3SXiaojuan Yang #include "hw/loongarch/virt.h"
116a8a506c3SXiaojuan Yang 
loongarch_cpu_set_irq(void * opaque,int irq,int level)117f757a2cdSXiaojuan Yang void loongarch_cpu_set_irq(void *opaque, int irq, int level)
118f757a2cdSXiaojuan Yang {
119f757a2cdSXiaojuan Yang     LoongArchCPU *cpu = opaque;
120f757a2cdSXiaojuan Yang     CPULoongArchState *env = &cpu->env;
121f757a2cdSXiaojuan Yang     CPUState *cs = CPU(cpu);
122f757a2cdSXiaojuan Yang 
123f757a2cdSXiaojuan Yang     if (irq < 0 || irq >= N_IRQS) {
124f757a2cdSXiaojuan Yang         return;
125f757a2cdSXiaojuan Yang     }
126f757a2cdSXiaojuan Yang 
1278dcbad51STianrui Zhao     if (kvm_enabled()) {
1288dcbad51STianrui Zhao         kvm_loongarch_set_interrupt(cpu, irq, level);
1298dcbad51STianrui Zhao     } else if (tcg_enabled()) {
130f757a2cdSXiaojuan Yang         env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
131f757a2cdSXiaojuan Yang         if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
132f757a2cdSXiaojuan Yang             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
133f757a2cdSXiaojuan Yang         } else {
134f757a2cdSXiaojuan Yang             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
135f757a2cdSXiaojuan Yang         }
136f757a2cdSXiaojuan Yang     }
1372d45085aSTianrui Zhao }
138f757a2cdSXiaojuan Yang 
cpu_loongarch_hw_interrupts_enabled(CPULoongArchState * env)139f757a2cdSXiaojuan Yang static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
140f757a2cdSXiaojuan Yang {
141f757a2cdSXiaojuan Yang     bool ret = 0;
142f757a2cdSXiaojuan Yang 
143f757a2cdSXiaojuan Yang     ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) &&
144f757a2cdSXiaojuan Yang           !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)));
145f757a2cdSXiaojuan Yang 
146f757a2cdSXiaojuan Yang     return ret;
147f757a2cdSXiaojuan Yang }
148f757a2cdSXiaojuan Yang 
149f757a2cdSXiaojuan Yang /* Check if there is pending and not masked out interrupt */
cpu_loongarch_hw_interrupts_pending(CPULoongArchState * env)150f757a2cdSXiaojuan Yang static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
151f757a2cdSXiaojuan Yang {
152f757a2cdSXiaojuan Yang     uint32_t pending;
153f757a2cdSXiaojuan Yang     uint32_t status;
154f757a2cdSXiaojuan Yang 
155f757a2cdSXiaojuan Yang     pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
156f757a2cdSXiaojuan Yang     status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
157f757a2cdSXiaojuan Yang 
15866997c42SMarkus Armbruster     return (pending & status) != 0;
159f757a2cdSXiaojuan Yang }
1602d45085aSTianrui Zhao #endif
161f757a2cdSXiaojuan Yang 
1622d45085aSTianrui Zhao #ifdef CONFIG_TCG
1632d45085aSTianrui Zhao #ifndef CONFIG_USER_ONLY
loongarch_cpu_do_interrupt(CPUState * cs)164f757a2cdSXiaojuan Yang static void loongarch_cpu_do_interrupt(CPUState *cs)
165f757a2cdSXiaojuan Yang {
166f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
167f757a2cdSXiaojuan Yang     bool update_badinstr = 1;
168f757a2cdSXiaojuan Yang     int cause = -1;
169f757a2cdSXiaojuan Yang     bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
170f757a2cdSXiaojuan Yang     uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
171f757a2cdSXiaojuan Yang 
172f757a2cdSXiaojuan Yang     if (cs->exception_index != EXCCODE_INT) {
173f757a2cdSXiaojuan Yang         qemu_log_mask(CPU_LOG_INT,
174f757a2cdSXiaojuan Yang                      "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
1751590154eSSong Gao                      " TLBRERA " TARGET_FMT_lx " exception: %d (%s)\n",
1761590154eSSong Gao                      __func__, env->pc, env->CSR_ERA, env->CSR_TLBRERA,
1771590154eSSong Gao                      cs->exception_index,
1781590154eSSong Gao                      loongarch_exception_name(cs->exception_index));
179f757a2cdSXiaojuan Yang     }
180f757a2cdSXiaojuan Yang 
181f757a2cdSXiaojuan Yang     switch (cs->exception_index) {
182f757a2cdSXiaojuan Yang     case EXCCODE_DBP:
183f757a2cdSXiaojuan Yang         env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1);
184f757a2cdSXiaojuan Yang         env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC);
185f757a2cdSXiaojuan Yang         goto set_DERA;
186f757a2cdSXiaojuan Yang     set_DERA:
187f757a2cdSXiaojuan Yang         env->CSR_DERA = env->pc;
188f757a2cdSXiaojuan Yang         env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
1892f6478ffSJiajie Chen         set_pc(env, env->CSR_EENTRY + 0x480);
190f757a2cdSXiaojuan Yang         break;
191f757a2cdSXiaojuan Yang     case EXCCODE_INT:
192f757a2cdSXiaojuan Yang         if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
193f757a2cdSXiaojuan Yang             env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1);
194f757a2cdSXiaojuan Yang             goto set_DERA;
195f757a2cdSXiaojuan Yang         }
196f757a2cdSXiaojuan Yang         QEMU_FALLTHROUGH;
197f757a2cdSXiaojuan Yang     case EXCCODE_PIF:
1988752b130SSong Gao     case EXCCODE_ADEF:
199f757a2cdSXiaojuan Yang         cause = cs->exception_index;
200f757a2cdSXiaojuan Yang         update_badinstr = 0;
201f757a2cdSXiaojuan Yang         break;
202f757a2cdSXiaojuan Yang     case EXCCODE_SYS:
203f757a2cdSXiaojuan Yang     case EXCCODE_BRK:
2047d552f0eSSong Gao     case EXCCODE_INE:
2057d552f0eSSong Gao     case EXCCODE_IPE:
2062419978cSRui Wang     case EXCCODE_FPD:
2077d552f0eSSong Gao     case EXCCODE_FPE:
208a3f3db5cSSong Gao     case EXCCODE_SXD:
209b8f1bdf3SSong Gao     case EXCCODE_ASXD:
2107d552f0eSSong Gao         env->CSR_BADV = env->pc;
2117d552f0eSSong Gao         QEMU_FALLTHROUGH;
2122e2ca3c8SSong Gao     case EXCCODE_BCE:
2137d552f0eSSong Gao     case EXCCODE_ADEM:
214f757a2cdSXiaojuan Yang     case EXCCODE_PIL:
215f757a2cdSXiaojuan Yang     case EXCCODE_PIS:
216f757a2cdSXiaojuan Yang     case EXCCODE_PME:
217f757a2cdSXiaojuan Yang     case EXCCODE_PNR:
218f757a2cdSXiaojuan Yang     case EXCCODE_PNX:
219f757a2cdSXiaojuan Yang     case EXCCODE_PPI:
220f757a2cdSXiaojuan Yang         cause = cs->exception_index;
221f757a2cdSXiaojuan Yang         break;
222f757a2cdSXiaojuan Yang     default:
223e4ad16f4SXiaojuan Yang         qemu_log("Error: exception(%d) has not been supported\n",
224e4ad16f4SXiaojuan Yang                  cs->exception_index);
225f757a2cdSXiaojuan Yang         abort();
226f757a2cdSXiaojuan Yang     }
227f757a2cdSXiaojuan Yang 
228f757a2cdSXiaojuan Yang     if (update_badinstr) {
229f757a2cdSXiaojuan Yang         env->CSR_BADI = cpu_ldl_code(env, env->pc);
230f757a2cdSXiaojuan Yang     }
231f757a2cdSXiaojuan Yang 
232f757a2cdSXiaojuan Yang     /* Save PLV and IE */
233f757a2cdSXiaojuan Yang     if (tlbfill) {
234f757a2cdSXiaojuan Yang         env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV,
235f757a2cdSXiaojuan Yang                                        FIELD_EX64(env->CSR_CRMD,
236f757a2cdSXiaojuan Yang                                        CSR_CRMD, PLV));
237f757a2cdSXiaojuan Yang         env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE,
238f757a2cdSXiaojuan Yang                                        FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE));
239f757a2cdSXiaojuan Yang         /* set the DA mode */
240f757a2cdSXiaojuan Yang         env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1);
241f757a2cdSXiaojuan Yang         env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0);
242f757a2cdSXiaojuan Yang         env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA,
243f757a2cdSXiaojuan Yang                                       PC, (env->pc >> 2));
244f757a2cdSXiaojuan Yang     } else {
245a6b129c8SSong Gao         env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE,
246a6b129c8SSong Gao                                     EXCODE_MCODE(cause));
247a6b129c8SSong Gao         env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ESUBCODE,
248a6b129c8SSong Gao                                     EXCODE_SUBCODE(cause));
249f757a2cdSXiaojuan Yang         env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV,
250f757a2cdSXiaojuan Yang                                    FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV));
251f757a2cdSXiaojuan Yang         env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE,
252f757a2cdSXiaojuan Yang                                    FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE));
253f757a2cdSXiaojuan Yang         env->CSR_ERA = env->pc;
254f757a2cdSXiaojuan Yang     }
255f757a2cdSXiaojuan Yang 
256f757a2cdSXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0);
257f757a2cdSXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0);
258f757a2cdSXiaojuan Yang 
25946233676SXiaojuan Yang     if (vec_size) {
26046233676SXiaojuan Yang         vec_size = (1 << vec_size) * 4;
26146233676SXiaojuan Yang     }
26246233676SXiaojuan Yang 
263f757a2cdSXiaojuan Yang     if  (cs->exception_index == EXCCODE_INT) {
264f757a2cdSXiaojuan Yang         /* Interrupt */
265f757a2cdSXiaojuan Yang         uint32_t vector = 0;
266f757a2cdSXiaojuan Yang         uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
267f757a2cdSXiaojuan Yang         pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
268f757a2cdSXiaojuan Yang 
269f757a2cdSXiaojuan Yang         /* Find the highest-priority interrupt. */
270f757a2cdSXiaojuan Yang         vector = 31 - clz32(pending);
2712f6478ffSJiajie Chen         set_pc(env, env->CSR_EENTRY + \
2722f6478ffSJiajie Chen                (EXCCODE_EXTERNAL_INT + vector) * vec_size);
273f757a2cdSXiaojuan Yang         qemu_log_mask(CPU_LOG_INT,
274f757a2cdSXiaojuan Yang                       "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx
275f757a2cdSXiaojuan Yang                       " cause %d\n" "    A " TARGET_FMT_lx " D "
276f757a2cdSXiaojuan Yang                       TARGET_FMT_lx " vector = %d ExC " TARGET_FMT_lx "ExS"
277f757a2cdSXiaojuan Yang                       TARGET_FMT_lx "\n",
278f757a2cdSXiaojuan Yang                       __func__, env->pc, env->CSR_ERA,
279f757a2cdSXiaojuan Yang                       cause, env->CSR_BADV, env->CSR_DERA, vector,
280f757a2cdSXiaojuan Yang                       env->CSR_ECFG, env->CSR_ESTAT);
281f757a2cdSXiaojuan Yang     } else {
282f757a2cdSXiaojuan Yang         if (tlbfill) {
2832f6478ffSJiajie Chen             set_pc(env, env->CSR_TLBRENTRY);
284f757a2cdSXiaojuan Yang         } else {
2852f6478ffSJiajie Chen             set_pc(env, env->CSR_EENTRY + EXCODE_MCODE(cause) * vec_size);
286f757a2cdSXiaojuan Yang         }
287f757a2cdSXiaojuan Yang         qemu_log_mask(CPU_LOG_INT,
288f757a2cdSXiaojuan Yang                       "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx
289f757a2cdSXiaojuan Yang                       " cause %d%s\n, ESTAT " TARGET_FMT_lx
290f757a2cdSXiaojuan Yang                       " EXCFG " TARGET_FMT_lx " BADVA " TARGET_FMT_lx
291f757a2cdSXiaojuan Yang                       "BADI " TARGET_FMT_lx " SYS_NUM " TARGET_FMT_lu
292f757a2cdSXiaojuan Yang                       " cpu %d asid " TARGET_FMT_lx "\n", __func__, env->pc,
293f757a2cdSXiaojuan Yang                       tlbfill ? env->CSR_TLBRERA : env->CSR_ERA,
294f757a2cdSXiaojuan Yang                       cause, tlbfill ? "(refill)" : "", env->CSR_ESTAT,
295f757a2cdSXiaojuan Yang                       env->CSR_ECFG,
296f757a2cdSXiaojuan Yang                       tlbfill ? env->CSR_TLBRBADV : env->CSR_BADV,
297f757a2cdSXiaojuan Yang                       env->CSR_BADI, env->gpr[11], cs->cpu_index,
298f757a2cdSXiaojuan Yang                       env->CSR_ASID);
299f757a2cdSXiaojuan Yang     }
300f757a2cdSXiaojuan Yang     cs->exception_index = -1;
301f757a2cdSXiaojuan Yang }
302f757a2cdSXiaojuan Yang 
loongarch_cpu_do_transaction_failed(CPUState * cs,hwaddr physaddr,vaddr addr,unsigned size,MMUAccessType access_type,int mmu_idx,MemTxAttrs attrs,MemTxResult response,uintptr_t retaddr)303f757a2cdSXiaojuan Yang static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
304f757a2cdSXiaojuan Yang                                                 vaddr addr, unsigned size,
305f757a2cdSXiaojuan Yang                                                 MMUAccessType access_type,
306f757a2cdSXiaojuan Yang                                                 int mmu_idx, MemTxAttrs attrs,
307f757a2cdSXiaojuan Yang                                                 MemTxResult response,
308f757a2cdSXiaojuan Yang                                                 uintptr_t retaddr)
309f757a2cdSXiaojuan Yang {
310f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
311f757a2cdSXiaojuan Yang 
312f757a2cdSXiaojuan Yang     if (access_type == MMU_INST_FETCH) {
313f757a2cdSXiaojuan Yang         do_raise_exception(env, EXCCODE_ADEF, retaddr);
314f757a2cdSXiaojuan Yang     } else {
315f757a2cdSXiaojuan Yang         do_raise_exception(env, EXCCODE_ADEM, retaddr);
316f757a2cdSXiaojuan Yang     }
317f757a2cdSXiaojuan Yang }
318f757a2cdSXiaojuan Yang 
loongarch_cpu_exec_interrupt(CPUState * cs,int interrupt_request)319f757a2cdSXiaojuan Yang static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
320f757a2cdSXiaojuan Yang {
321f757a2cdSXiaojuan Yang     if (interrupt_request & CPU_INTERRUPT_HARD) {
322f3b603b9SPhilippe Mathieu-Daudé         CPULoongArchState *env = cpu_env(cs);
323f757a2cdSXiaojuan Yang 
324f757a2cdSXiaojuan Yang         if (cpu_loongarch_hw_interrupts_enabled(env) &&
325f757a2cdSXiaojuan Yang             cpu_loongarch_hw_interrupts_pending(env)) {
326f757a2cdSXiaojuan Yang             /* Raise it */
327f757a2cdSXiaojuan Yang             cs->exception_index = EXCCODE_INT;
328f757a2cdSXiaojuan Yang             loongarch_cpu_do_interrupt(cs);
329f757a2cdSXiaojuan Yang             return true;
330f757a2cdSXiaojuan Yang         }
331f757a2cdSXiaojuan Yang     }
332f757a2cdSXiaojuan Yang     return false;
333f757a2cdSXiaojuan Yang }
3340093b9a5SSong Gao #endif
335f757a2cdSXiaojuan Yang 
loongarch_cpu_synchronize_from_tb(CPUState * cs,const TranslationBlock * tb)336228021f0SSong Gao static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
337228021f0SSong Gao                                               const TranslationBlock *tb)
338228021f0SSong Gao {
339b254c342SPhilippe Mathieu-Daudé     tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL));
340f3b603b9SPhilippe Mathieu-Daudé     set_pc(cpu_env(cs), tb->pc);
341228021f0SSong Gao }
342ab27940fSRichard Henderson 
loongarch_restore_state_to_opc(CPUState * cs,const TranslationBlock * tb,const uint64_t * data)343ab27940fSRichard Henderson static void loongarch_restore_state_to_opc(CPUState *cs,
344ab27940fSRichard Henderson                                            const TranslationBlock *tb,
345ab27940fSRichard Henderson                                            const uint64_t *data)
346ab27940fSRichard Henderson {
347f3b603b9SPhilippe Mathieu-Daudé     set_pc(cpu_env(cs), data[0]);
348ab27940fSRichard Henderson }
349228021f0SSong Gao #endif /* CONFIG_TCG */
350228021f0SSong Gao 
loongarch_cpu_has_work(CPUState * cs)351f757a2cdSXiaojuan Yang static bool loongarch_cpu_has_work(CPUState *cs)
352f757a2cdSXiaojuan Yang {
3530093b9a5SSong Gao #ifdef CONFIG_USER_ONLY
3540093b9a5SSong Gao     return true;
3550093b9a5SSong Gao #else
356f757a2cdSXiaojuan Yang     bool has_work = false;
357f757a2cdSXiaojuan Yang 
358f757a2cdSXiaojuan Yang     if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
359f3b603b9SPhilippe Mathieu-Daudé         cpu_loongarch_hw_interrupts_pending(cpu_env(cs))) {
360f757a2cdSXiaojuan Yang         has_work = true;
361f757a2cdSXiaojuan Yang     }
362f757a2cdSXiaojuan Yang 
363f757a2cdSXiaojuan Yang     return has_work;
3640093b9a5SSong Gao #endif
365f757a2cdSXiaojuan Yang }
366f757a2cdSXiaojuan Yang 
loongarch_cpu_mmu_index(CPUState * cs,bool ifetch)367a120d320SRichard Henderson static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch)
368a72a1b10SRichard Henderson {
369a72a1b10SRichard Henderson     CPULoongArchState *env = cpu_env(cs);
370a72a1b10SRichard Henderson 
371a72a1b10SRichard Henderson     if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) {
372a72a1b10SRichard Henderson         return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
373a72a1b10SRichard Henderson     }
3743f262d25SRichard Henderson     return MMU_DA_IDX;
375a72a1b10SRichard Henderson }
376a72a1b10SRichard Henderson 
loongarch_la464_initfn(Object * obj)377228021f0SSong Gao static void loongarch_la464_initfn(Object *obj)
378228021f0SSong Gao {
379228021f0SSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
380228021f0SSong Gao     CPULoongArchState *env = &cpu->env;
381228021f0SSong Gao     int i;
382228021f0SSong Gao 
383228021f0SSong Gao     for (i = 0; i < 21; i++) {
384228021f0SSong Gao         env->cpucfg[i] = 0x0;
385228021f0SSong Gao     }
386228021f0SSong Gao 
387fda3f15bSXiaojuan Yang     cpu->dtb_compatible = "loongarch,Loongson-3A5000";
388228021f0SSong Gao     env->cpucfg[0] = 0x14c010;  /* PRID */
389228021f0SSong Gao 
390228021f0SSong Gao     uint32_t data = 0;
391228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
392228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
393228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
394228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
395228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
396228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, UAL, 1);
397228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, RI, 1);
398228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, EP, 1);
399228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
400228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, HP, 1);
401228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
402228021f0SSong Gao     env->cpucfg[1] = data;
403228021f0SSong Gao 
404228021f0SSong Gao     data = 0;
405228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, FP, 1);
406228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
407228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
408228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
409c6c2fec4SSong Gao     data = FIELD_DP32(data, CPUCFG2, LSX, 1),
4102cd81e37SSong Gao     data = FIELD_DP32(data, CPUCFG2, LASX, 1),
411228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
412228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
4130b360727SSong Gao     data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
414228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG2, LAM, 1);
415228021f0SSong Gao     env->cpucfg[2] = data;
416228021f0SSong Gao 
417228021f0SSong Gao     env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
418228021f0SSong Gao 
419228021f0SSong Gao     data = 0;
420228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
421228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
422228021f0SSong Gao     env->cpucfg[5] = data;
423228021f0SSong Gao 
424228021f0SSong Gao     data = 0;
425228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
426228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
427228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
428228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
429228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
430228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
431228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
432228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
433228021f0SSong Gao     env->cpucfg[16] = data;
434228021f0SSong Gao 
435228021f0SSong Gao     data = 0;
436228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 3);
437228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 8);
438228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG17, L1IU_SIZE, 6);
439228021f0SSong Gao     env->cpucfg[17] = data;
440228021f0SSong Gao 
441228021f0SSong Gao     data = 0;
442228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 3);
443228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 8);
444228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG18, L1D_SIZE, 6);
445228021f0SSong Gao     env->cpucfg[18] = data;
446228021f0SSong Gao 
447228021f0SSong Gao     data = 0;
448228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 15);
449228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 8);
450228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG19, L2IU_SIZE, 6);
451228021f0SSong Gao     env->cpucfg[19] = data;
452228021f0SSong Gao 
453228021f0SSong Gao     data = 0;
454228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 15);
455228021f0SSong Gao     data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 14);
456fa90456fSXiaojuan Yang     data = FIELD_DP32(data, CPUCFG20, L3IU_SIZE, 6);
457228021f0SSong Gao     env->cpucfg[20] = data;
458398cecb9SXiaojuan Yang 
459398cecb9SXiaojuan Yang     env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
460bba1c36dSSong Gao 
461bba1c36dSSong Gao     env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8);
462bba1c36dSSong Gao     env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f);
463bba1c36dSSong Gao     env->CSR_PRCFG1 = FIELD_DP64(env->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7);
464bba1c36dSSong Gao 
465bba1c36dSSong Gao     env->CSR_PRCFG2 = 0x3ffff000;
466bba1c36dSSong Gao 
467bba1c36dSSong Gao     env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
468bba1c36dSSong Gao     env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
469bba1c36dSSong Gao     env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
470bba1c36dSSong Gao     env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
471bba1c36dSSong Gao 
472464136ceSSong Gao     loongarch_cpu_post_init(obj);
473228021f0SSong Gao }
474228021f0SSong Gao 
loongarch_la132_initfn(Object * obj)475bb8710cfSJiajie Chen static void loongarch_la132_initfn(Object *obj)
476bb8710cfSJiajie Chen {
477bb8710cfSJiajie Chen     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
478bb8710cfSJiajie Chen     CPULoongArchState *env = &cpu->env;
479bb8710cfSJiajie Chen 
480bb8710cfSJiajie Chen     int i;
481bb8710cfSJiajie Chen 
482bb8710cfSJiajie Chen     for (i = 0; i < 21; i++) {
483bb8710cfSJiajie Chen         env->cpucfg[i] = 0x0;
484bb8710cfSJiajie Chen     }
485bb8710cfSJiajie Chen 
486bb8710cfSJiajie Chen     cpu->dtb_compatible = "loongarch,Loongson-1C103";
487bb8710cfSJiajie Chen     env->cpucfg[0] = 0x148042;  /* PRID */
488bb8710cfSJiajie Chen 
489bb8710cfSJiajie Chen     uint32_t data = 0;
490bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
491bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
492bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
493bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
494bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
495bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, UAL, 1);
496bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, RI, 0);
497bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, EP, 0);
498bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
499bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, HP, 1);
500bb8710cfSJiajie Chen     data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
501bb8710cfSJiajie Chen     env->cpucfg[1] = data;
502bb8710cfSJiajie Chen }
503bb8710cfSJiajie Chen 
loongarch_max_initfn(Object * obj)504d6f07732SSong Gao static void loongarch_max_initfn(Object *obj)
505d6f07732SSong Gao {
506d6f07732SSong Gao     /* '-cpu max' for TCG: we use cpu la464. */
507d6f07732SSong Gao     loongarch_la464_initfn(obj);
508d6f07732SSong Gao }
509d6f07732SSong Gao 
loongarch_cpu_reset_hold(Object * obj,ResetType type)510ad80e367SPeter Maydell static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
511228021f0SSong Gao {
512f78b49aeSPeter Maydell     CPUState *cs = CPU(obj);
513348802b5SPhilippe Mathieu-Daudé     LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
514f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
515228021f0SSong Gao 
516f78b49aeSPeter Maydell     if (lacc->parent_phases.hold) {
517ad80e367SPeter Maydell         lacc->parent_phases.hold(obj, type);
518f78b49aeSPeter Maydell     }
519228021f0SSong Gao 
5206f703a48SBibo Mao #ifdef CONFIG_TCG
521228021f0SSong Gao     env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
5226f703a48SBibo Mao #endif
523228021f0SSong Gao     env->fcsr0 = 0x0;
524228021f0SSong Gao 
525398cecb9SXiaojuan Yang     int n;
5263ef4b21aSSong Gao     /* Set csr registers value after reset, see the manual 6.4. */
527398cecb9SXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0);
528398cecb9SXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0);
529398cecb9SXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1);
530398cecb9SXiaojuan Yang     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0);
5313ef4b21aSSong Gao     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATF, 0);
5323ef4b21aSSong Gao     env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 0);
533398cecb9SXiaojuan Yang 
534398cecb9SXiaojuan Yang     env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, FPE, 0);
535398cecb9SXiaojuan Yang     env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, SXE, 0);
536398cecb9SXiaojuan Yang     env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, ASXE, 0);
537398cecb9SXiaojuan Yang     env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, BTE, 0);
538398cecb9SXiaojuan Yang 
539398cecb9SXiaojuan Yang     env->CSR_MISC = 0;
540398cecb9SXiaojuan Yang 
541398cecb9SXiaojuan Yang     env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, VS, 0);
542398cecb9SXiaojuan Yang     env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, LIE, 0);
543398cecb9SXiaojuan Yang 
544398cecb9SXiaojuan Yang     env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
545398cecb9SXiaojuan Yang     env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
54662784656STianrui Zhao     env->CSR_CPUID = cs->cpu_index;
547398cecb9SXiaojuan Yang     env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
548398cecb9SXiaojuan Yang     env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
549398cecb9SXiaojuan Yang     env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
550398cecb9SXiaojuan Yang     env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
55162784656STianrui Zhao     env->CSR_TID = cs->cpu_index;
552a840d70eSBibo Mao     /*
553a840d70eSBibo Mao      * Workaround for edk2-stable202408, CSR PGD register is set only if
554a840d70eSBibo Mao      * its value is equal to zero for boot cpu, it causes reboot issue.
555a840d70eSBibo Mao      *
556a840d70eSBibo Mao      * Here clear CSR registers relative with TLB.
557a840d70eSBibo Mao      */
558a840d70eSBibo Mao     env->CSR_PGDH = 0;
559a840d70eSBibo Mao     env->CSR_PGDL = 0;
560a840d70eSBibo Mao     env->CSR_PWCL = 0;
561a840d70eSBibo Mao     env->CSR_PWCH = 0;
562a840d70eSBibo Mao     env->CSR_STLBPS = 0;
563a840d70eSBibo Mao     env->CSR_EENTRY = 0;
564a840d70eSBibo Mao     env->CSR_TLBRENTRY = 0;
565a840d70eSBibo Mao     env->CSR_MERRENTRY = 0;
566398cecb9SXiaojuan Yang 
567398cecb9SXiaojuan Yang     for (n = 0; n < 4; n++) {
568398cecb9SXiaojuan Yang         env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0);
569398cecb9SXiaojuan Yang         env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0);
570398cecb9SXiaojuan Yang         env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV2, 0);
571398cecb9SXiaojuan Yang         env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV3, 0);
572398cecb9SXiaojuan Yang     }
573398cecb9SXiaojuan Yang 
5740093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
575f757a2cdSXiaojuan Yang     env->pc = 0x1c000000;
5766f703a48SBibo Mao #ifdef CONFIG_TCG
5773517fb72SSong Gao     memset(env->tlb, 0, sizeof(env->tlb));
5786f703a48SBibo Mao #endif
579f8447436STianrui Zhao     if (kvm_enabled()) {
580a724f5a8SBibo Mao         kvm_arch_reset_vcpu(cs);
581f8447436STianrui Zhao     }
5820093b9a5SSong Gao #endif
583f757a2cdSXiaojuan Yang 
5842d45085aSTianrui Zhao #ifdef CONFIG_TCG
585d578ca6cSSong Gao     restore_fp_status(env);
5862d45085aSTianrui Zhao #endif
587228021f0SSong Gao     cs->exception_index = -1;
588228021f0SSong Gao }
589228021f0SSong Gao 
loongarch_cpu_disas_set_info(CPUState * s,disassemble_info * info)590228021f0SSong Gao static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
591228021f0SSong Gao {
592228021f0SSong Gao     info->print_insn = print_insn_loongarch;
593228021f0SSong Gao }
594228021f0SSong Gao 
loongarch_cpu_realizefn(DeviceState * dev,Error ** errp)595228021f0SSong Gao static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
596228021f0SSong Gao {
597228021f0SSong Gao     CPUState *cs = CPU(dev);
598228021f0SSong Gao     LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
599228021f0SSong Gao     Error *local_err = NULL;
600228021f0SSong Gao 
601228021f0SSong Gao     cpu_exec_realizefn(cs, &local_err);
602228021f0SSong Gao     if (local_err != NULL) {
603228021f0SSong Gao         error_propagate(errp, local_err);
604228021f0SSong Gao         return;
605228021f0SSong Gao     }
606228021f0SSong Gao 
607ca61e750SXiaojuan Yang     loongarch_cpu_register_gdb_regs_for_features(cs);
608ca61e750SXiaojuan Yang 
609228021f0SSong Gao     cpu_reset(cs);
610228021f0SSong Gao     qemu_init_vcpu(cs);
611228021f0SSong Gao 
612228021f0SSong Gao     lacc->parent_realize(dev, errp);
613228021f0SSong Gao }
614228021f0SSong Gao 
loongarch_get_lsx(Object * obj,Error ** errp)615464136ceSSong Gao static bool loongarch_get_lsx(Object *obj, Error **errp)
616464136ceSSong Gao {
617464136ceSSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
618464136ceSSong Gao     bool ret;
619464136ceSSong Gao 
620464136ceSSong Gao     if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
621464136ceSSong Gao         ret = true;
622464136ceSSong Gao     } else {
623464136ceSSong Gao         ret = false;
624464136ceSSong Gao     }
625464136ceSSong Gao     return ret;
626464136ceSSong Gao }
627464136ceSSong Gao 
loongarch_set_lsx(Object * obj,bool value,Error ** errp)628464136ceSSong Gao static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
629464136ceSSong Gao {
630464136ceSSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
631464136ceSSong Gao 
632464136ceSSong Gao     if (value) {
633464136ceSSong Gao         cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
634464136ceSSong Gao     } else {
635464136ceSSong Gao         cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0);
636464136ceSSong Gao         cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
637464136ceSSong Gao     }
638464136ceSSong Gao }
639464136ceSSong Gao 
loongarch_get_lasx(Object * obj,Error ** errp)640464136ceSSong Gao static bool loongarch_get_lasx(Object *obj, Error **errp)
641464136ceSSong Gao {
642464136ceSSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
643464136ceSSong Gao     bool ret;
644464136ceSSong Gao 
645464136ceSSong Gao     if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) {
646464136ceSSong Gao         ret = true;
647464136ceSSong Gao     } else {
648464136ceSSong Gao         ret = false;
649464136ceSSong Gao     }
650464136ceSSong Gao     return ret;
651464136ceSSong Gao }
652464136ceSSong Gao 
loongarch_set_lasx(Object * obj,bool value,Error ** errp)653464136ceSSong Gao static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
654464136ceSSong Gao {
655464136ceSSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
656464136ceSSong Gao 
657464136ceSSong Gao     if (value) {
658464136ceSSong Gao 	if (!FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) {
659464136ceSSong Gao             cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1);
660464136ceSSong Gao 	}
661464136ceSSong Gao         cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 1);
662464136ceSSong Gao     } else {
663464136ceSSong Gao         cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0);
664464136ceSSong Gao     }
665464136ceSSong Gao }
666464136ceSSong Gao 
loongarch_get_lbt(Object * obj,Error ** errp)667c23a53d8SBibo Mao static bool loongarch_get_lbt(Object *obj, Error **errp)
668c23a53d8SBibo Mao {
669c23a53d8SBibo Mao     return LOONGARCH_CPU(obj)->lbt != ON_OFF_AUTO_OFF;
670c23a53d8SBibo Mao }
671c23a53d8SBibo Mao 
loongarch_set_lbt(Object * obj,bool value,Error ** errp)672c23a53d8SBibo Mao static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
673c23a53d8SBibo Mao {
674c23a53d8SBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
675c23a53d8SBibo Mao 
676c23a53d8SBibo Mao     cpu->lbt = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
677c23a53d8SBibo Mao }
678c23a53d8SBibo Mao 
loongarch_get_pmu(Object * obj,Error ** errp)679*6edd2a9bSBibo Mao static bool loongarch_get_pmu(Object *obj, Error **errp)
680*6edd2a9bSBibo Mao {
681*6edd2a9bSBibo Mao     return LOONGARCH_CPU(obj)->pmu != ON_OFF_AUTO_OFF;
682*6edd2a9bSBibo Mao }
683*6edd2a9bSBibo Mao 
loongarch_set_pmu(Object * obj,bool value,Error ** errp)684*6edd2a9bSBibo Mao static void loongarch_set_pmu(Object *obj, bool value, Error **errp)
685*6edd2a9bSBibo Mao {
686*6edd2a9bSBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
687*6edd2a9bSBibo Mao 
688*6edd2a9bSBibo Mao     cpu->pmu = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
689*6edd2a9bSBibo Mao }
690*6edd2a9bSBibo Mao 
loongarch_cpu_post_init(Object * obj)691464136ceSSong Gao void loongarch_cpu_post_init(Object *obj)
692464136ceSSong Gao {
693c23a53d8SBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
694c23a53d8SBibo Mao 
695464136ceSSong Gao     object_property_add_bool(obj, "lsx", loongarch_get_lsx,
696464136ceSSong Gao                              loongarch_set_lsx);
697464136ceSSong Gao     object_property_add_bool(obj, "lasx", loongarch_get_lasx,
698464136ceSSong Gao                              loongarch_set_lasx);
699c23a53d8SBibo Mao     /* lbt is enabled only in kvm mode, not supported in tcg mode */
700c23a53d8SBibo Mao     if (kvm_enabled()) {
701c23a53d8SBibo Mao         cpu->lbt = ON_OFF_AUTO_AUTO;
702c23a53d8SBibo Mao         object_property_add_bool(obj, "lbt", loongarch_get_lbt,
703c23a53d8SBibo Mao                                  loongarch_set_lbt);
704c23a53d8SBibo Mao         object_property_set_description(obj, "lbt",
705c23a53d8SBibo Mao                                    "Set off to disable Binary Tranlation.");
706*6edd2a9bSBibo Mao 
707*6edd2a9bSBibo Mao         cpu->pmu = ON_OFF_AUTO_AUTO;
708*6edd2a9bSBibo Mao         object_property_add_bool(obj, "pmu", loongarch_get_pmu,
709*6edd2a9bSBibo Mao                                  loongarch_set_pmu);
710*6edd2a9bSBibo Mao         object_property_set_description(obj, "pmu",
711*6edd2a9bSBibo Mao                                    "Set off to performance monitor unit.");
712*6edd2a9bSBibo Mao 
713c23a53d8SBibo Mao     } else {
714c23a53d8SBibo Mao         cpu->lbt = ON_OFF_AUTO_OFF;
715c23a53d8SBibo Mao     }
716464136ceSSong Gao }
717464136ceSSong Gao 
loongarch_cpu_init(Object * obj)718228021f0SSong Gao static void loongarch_cpu_init(Object *obj)
719228021f0SSong Gao {
7200093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
7218fa08d7eSRichard Henderson     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
7228fa08d7eSRichard Henderson 
723f757a2cdSXiaojuan Yang     qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
7242d45085aSTianrui Zhao #ifdef CONFIG_TCG
725dd615fa4SXiaojuan Yang     timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
726dd615fa4SXiaojuan Yang                   &loongarch_constant_timer_cb, cpu);
7272d45085aSTianrui Zhao #endif
7280093b9a5SSong Gao #endif
729228021f0SSong Gao }
730228021f0SSong Gao 
loongarch_cpu_class_by_name(const char * cpu_model)731228021f0SSong Gao static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
732228021f0SSong Gao {
733228021f0SSong Gao     ObjectClass *oc;
734228021f0SSong Gao 
735c254f7afSXiaojuan Yang     oc = object_class_by_name(cpu_model);
736c254f7afSXiaojuan Yang     if (!oc) {
737c254f7afSXiaojuan Yang         g_autofree char *typename
738c254f7afSXiaojuan Yang             = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
739228021f0SSong Gao         oc = object_class_by_name(typename);
740c254f7afSXiaojuan Yang     }
741c254f7afSXiaojuan Yang 
742228021f0SSong Gao     return oc;
743228021f0SSong Gao }
744228021f0SSong Gao 
loongarch_cpu_dump_state(CPUState * cs,FILE * f,int flags)745228021f0SSong Gao void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
746228021f0SSong Gao {
747f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
748228021f0SSong Gao     int i;
749228021f0SSong Gao 
750228021f0SSong Gao     qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
7516f703a48SBibo Mao     qemu_fprintf(f, " FCSR0 0x%08x\n", env->fcsr0);
752228021f0SSong Gao 
753228021f0SSong Gao     /* gpr */
754228021f0SSong Gao     for (i = 0; i < 32; i++) {
755228021f0SSong Gao         if ((i & 3) == 0) {
756228021f0SSong Gao             qemu_fprintf(f, " GPR%02d:", i);
757228021f0SSong Gao         }
758228021f0SSong Gao         qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
759228021f0SSong Gao         if ((i & 3) == 3) {
760228021f0SSong Gao             qemu_fprintf(f, "\n");
761228021f0SSong Gao         }
762228021f0SSong Gao     }
763228021f0SSong Gao 
7647e1c521eSXiaojuan Yang     qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
7657e1c521eSXiaojuan Yang     qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
7667e1c521eSXiaojuan Yang     qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
7677e1c521eSXiaojuan Yang     qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
7687e1c521eSXiaojuan Yang     qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
7697e1c521eSXiaojuan Yang     qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
7707e1c521eSXiaojuan Yang     qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
7717e1c521eSXiaojuan Yang     qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
7727e1c521eSXiaojuan Yang     qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
7737e1c521eSXiaojuan Yang                  " PRCFG3=%016" PRIx64 "\n",
77478f932eaSlanyanzhi                  env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
7757e1c521eSXiaojuan Yang     qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
7767e1c521eSXiaojuan Yang     qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
7777e1c521eSXiaojuan Yang     qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
778be45144bSBibo Mao     qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG);
779be45144bSBibo Mao     qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL);
7807e1c521eSXiaojuan Yang 
781228021f0SSong Gao     /* fpr */
782228021f0SSong Gao     if (flags & CPU_DUMP_FPU) {
783228021f0SSong Gao         for (i = 0; i < 32; i++) {
78416f5396cSSong Gao             qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i].vreg.D(0));
785228021f0SSong Gao             if ((i & 3) == 3) {
786228021f0SSong Gao                 qemu_fprintf(f, "\n");
787228021f0SSong Gao             }
788228021f0SSong Gao         }
789228021f0SSong Gao     }
790228021f0SSong Gao }
791228021f0SSong Gao 
792228021f0SSong Gao #ifdef CONFIG_TCG
793228021f0SSong Gao #include "hw/core/tcg-cpu-ops.h"
794228021f0SSong Gao 
7952889fb8bSRichard Henderson static const TCGCPUOps loongarch_tcg_ops = {
796228021f0SSong Gao     .initialize = loongarch_translate_init,
797228021f0SSong Gao     .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
798ab27940fSRichard Henderson     .restore_state_to_opc = loongarch_restore_state_to_opc,
7997e1c521eSXiaojuan Yang 
8000093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
8017e1c521eSXiaojuan Yang     .tlb_fill = loongarch_cpu_tlb_fill,
802f757a2cdSXiaojuan Yang     .cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
8034f7b1ecbSPeter Maydell     .cpu_exec_halt = loongarch_cpu_has_work,
804f757a2cdSXiaojuan Yang     .do_interrupt = loongarch_cpu_do_interrupt,
805f757a2cdSXiaojuan Yang     .do_transaction_failed = loongarch_cpu_do_transaction_failed,
8060093b9a5SSong Gao #endif
807228021f0SSong Gao };
808228021f0SSong Gao #endif /* CONFIG_TCG */
809228021f0SSong Gao 
8100093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
8117e1c521eSXiaojuan Yang #include "hw/core/sysemu-cpu-ops.h"
8127e1c521eSXiaojuan Yang 
8137e1c521eSXiaojuan Yang static const struct SysemuCPUOps loongarch_sysemu_ops = {
81432c22cc4SBibo Mao     .write_elf64_note = loongarch_cpu_write_elf64_note,
8157e1c521eSXiaojuan Yang     .get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
8167e1c521eSXiaojuan Yang };
81714f21f67SBibo Mao 
loongarch_cpu_get_arch_id(CPUState * cs)81814f21f67SBibo Mao static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
81914f21f67SBibo Mao {
82014f21f67SBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
82114f21f67SBibo Mao 
82214f21f67SBibo Mao     return cpu->phy_id;
82314f21f67SBibo Mao }
8240093b9a5SSong Gao #endif
8257e1c521eSXiaojuan Yang 
loongarch_cpu_class_init(ObjectClass * c,void * data)826228021f0SSong Gao static void loongarch_cpu_class_init(ObjectClass *c, void *data)
827228021f0SSong Gao {
828228021f0SSong Gao     LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
829228021f0SSong Gao     CPUClass *cc = CPU_CLASS(c);
830228021f0SSong Gao     DeviceClass *dc = DEVICE_CLASS(c);
831f78b49aeSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(c);
832228021f0SSong Gao 
833228021f0SSong Gao     device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
834228021f0SSong Gao                                     &lacc->parent_realize);
835f78b49aeSPeter Maydell     resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL,
836f78b49aeSPeter Maydell                                        &lacc->parent_phases);
837228021f0SSong Gao 
838228021f0SSong Gao     cc->class_by_name = loongarch_cpu_class_by_name;
839f757a2cdSXiaojuan Yang     cc->has_work = loongarch_cpu_has_work;
840a72a1b10SRichard Henderson     cc->mmu_index = loongarch_cpu_mmu_index;
841228021f0SSong Gao     cc->dump_state = loongarch_cpu_dump_state;
842228021f0SSong Gao     cc->set_pc = loongarch_cpu_set_pc;
843e4fdf9dfSRichard Henderson     cc->get_pc = loongarch_cpu_get_pc;
8440093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
84514f21f67SBibo Mao     cc->get_arch_id = loongarch_cpu_get_arch_id;
84667ebd42aSXiaojuan Yang     dc->vmsd = &vmstate_loongarch_cpu;
8477e1c521eSXiaojuan Yang     cc->sysemu_ops = &loongarch_sysemu_ops;
8480093b9a5SSong Gao #endif
849228021f0SSong Gao     cc->disas_set_info = loongarch_cpu_disas_set_info;
850ca61e750SXiaojuan Yang     cc->gdb_read_register = loongarch_cpu_gdb_read_register;
851ca61e750SXiaojuan Yang     cc->gdb_write_register = loongarch_cpu_gdb_write_register;
852ca61e750SXiaojuan Yang     cc->gdb_stop_before_watchpoint = true;
853ca61e750SXiaojuan Yang 
854228021f0SSong Gao #ifdef CONFIG_TCG
855228021f0SSong Gao     cc->tcg_ops = &loongarch_tcg_ops;
856228021f0SSong Gao #endif
857228021f0SSong Gao }
858228021f0SSong Gao 
loongarch32_gdb_arch_name(CPUState * cs)859a6506838SAkihiko Odaki static const gchar *loongarch32_gdb_arch_name(CPUState *cs)
860ebda3036SJiajie Chen {
861a6506838SAkihiko Odaki     return "loongarch32";
862ebda3036SJiajie Chen }
863ebda3036SJiajie Chen 
loongarch32_cpu_class_init(ObjectClass * c,void * data)8646cbba3e9SJiajie Chen static void loongarch32_cpu_class_init(ObjectClass *c, void *data)
8656cbba3e9SJiajie Chen {
866ebda3036SJiajie Chen     CPUClass *cc = CPU_CLASS(c);
867ebda3036SJiajie Chen 
868ebda3036SJiajie Chen     cc->gdb_core_xml_file = "loongarch-base32.xml";
869ebda3036SJiajie Chen     cc->gdb_arch_name = loongarch32_gdb_arch_name;
8706cbba3e9SJiajie Chen }
8716cbba3e9SJiajie Chen 
loongarch64_gdb_arch_name(CPUState * cs)872a6506838SAkihiko Odaki static const gchar *loongarch64_gdb_arch_name(CPUState *cs)
873e389358eSPhilippe Mathieu-Daudé {
874a6506838SAkihiko Odaki     return "loongarch64";
875e389358eSPhilippe Mathieu-Daudé }
876e389358eSPhilippe Mathieu-Daudé 
loongarch64_cpu_class_init(ObjectClass * c,void * data)877e389358eSPhilippe Mathieu-Daudé static void loongarch64_cpu_class_init(ObjectClass *c, void *data)
878e389358eSPhilippe Mathieu-Daudé {
879e389358eSPhilippe Mathieu-Daudé     CPUClass *cc = CPU_CLASS(c);
880e389358eSPhilippe Mathieu-Daudé 
881e389358eSPhilippe Mathieu-Daudé     cc->gdb_core_xml_file = "loongarch-base64.xml";
882e389358eSPhilippe Mathieu-Daudé     cc->gdb_arch_name = loongarch64_gdb_arch_name;
883e389358eSPhilippe Mathieu-Daudé }
884e389358eSPhilippe Mathieu-Daudé 
885146f2354SPhilippe Mathieu-Daudé #define DEFINE_LOONGARCH_CPU_TYPE(size, model, initfn) \
886228021f0SSong Gao     { \
887146f2354SPhilippe Mathieu-Daudé         .parent = TYPE_LOONGARCH##size##_CPU, \
888228021f0SSong Gao         .instance_init = initfn, \
889228021f0SSong Gao         .name = LOONGARCH_CPU_TYPE_NAME(model), \
890228021f0SSong Gao     }
891228021f0SSong Gao 
892228021f0SSong Gao static const TypeInfo loongarch_cpu_type_infos[] = {
893228021f0SSong Gao     {
894228021f0SSong Gao         .name = TYPE_LOONGARCH_CPU,
895228021f0SSong Gao         .parent = TYPE_CPU,
896228021f0SSong Gao         .instance_size = sizeof(LoongArchCPU),
897f669c992SRichard Henderson         .instance_align = __alignof(LoongArchCPU),
898228021f0SSong Gao         .instance_init = loongarch_cpu_init,
899228021f0SSong Gao 
900228021f0SSong Gao         .abstract = true,
901228021f0SSong Gao         .class_size = sizeof(LoongArchCPUClass),
902228021f0SSong Gao         .class_init = loongarch_cpu_class_init,
903228021f0SSong Gao     },
904146f2354SPhilippe Mathieu-Daudé     {
9056cbba3e9SJiajie Chen         .name = TYPE_LOONGARCH32_CPU,
9066cbba3e9SJiajie Chen         .parent = TYPE_LOONGARCH_CPU,
9076cbba3e9SJiajie Chen 
9086cbba3e9SJiajie Chen         .abstract = true,
9096cbba3e9SJiajie Chen         .class_init = loongarch32_cpu_class_init,
9106cbba3e9SJiajie Chen     },
9116cbba3e9SJiajie Chen     {
912146f2354SPhilippe Mathieu-Daudé         .name = TYPE_LOONGARCH64_CPU,
913146f2354SPhilippe Mathieu-Daudé         .parent = TYPE_LOONGARCH_CPU,
914146f2354SPhilippe Mathieu-Daudé 
915146f2354SPhilippe Mathieu-Daudé         .abstract = true,
916e389358eSPhilippe Mathieu-Daudé         .class_init = loongarch64_cpu_class_init,
917146f2354SPhilippe Mathieu-Daudé     },
918146f2354SPhilippe Mathieu-Daudé     DEFINE_LOONGARCH_CPU_TYPE(64, "la464", loongarch_la464_initfn),
919bb8710cfSJiajie Chen     DEFINE_LOONGARCH_CPU_TYPE(32, "la132", loongarch_la132_initfn),
920d6f07732SSong Gao     DEFINE_LOONGARCH_CPU_TYPE(64, "max", loongarch_max_initfn),
921228021f0SSong Gao };
922228021f0SSong Gao 
923228021f0SSong Gao DEFINE_TYPES(loongarch_cpu_type_infos)
924