]> Git Repo - qemu.git/blob - target/loongarch/cpu.c
1f8e37906a557dfeb1eb0455afb363c43446ff07
[qemu.git] / target / loongarch / cpu.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * QEMU LoongArch CPU
4  *
5  * Copyright (c) 2021 Loongson Technology Corporation Limited
6  */
7
8 #include "qemu/osdep.h"
9 #include "qemu/log.h"
10 #include "qemu/qemu-print.h"
11 #include "qapi/error.h"
12 #include "qemu/module.h"
13 #include "sysemu/qtest.h"
14 #include "exec/exec-all.h"
15 #include "qapi/qapi-commands-machine-target.h"
16 #include "cpu.h"
17 #include "internals.h"
18 #include "fpu/softfloat-helpers.h"
19
20 const char * const regnames[32] = {
21     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
22     "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
23     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
24     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
25 };
26
27 const char * const fregnames[32] = {
28     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
29     "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
30     "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
31     "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
32 };
33
34 static const char * const excp_names[] = {
35     [EXCCODE_INT] = "Interrupt",
36     [EXCCODE_PIL] = "Page invalid exception for load",
37     [EXCCODE_PIS] = "Page invalid exception for store",
38     [EXCCODE_PIF] = "Page invalid exception for fetch",
39     [EXCCODE_PME] = "Page modified exception",
40     [EXCCODE_PNR] = "Page Not Readable exception",
41     [EXCCODE_PNX] = "Page Not Executable exception",
42     [EXCCODE_PPI] = "Page Privilege error",
43     [EXCCODE_ADEF] = "Address error for instruction fetch",
44     [EXCCODE_ADEM] = "Address error for Memory access",
45     [EXCCODE_SYS] = "Syscall",
46     [EXCCODE_BRK] = "Break",
47     [EXCCODE_INE] = "Instruction Non-Existent",
48     [EXCCODE_IPE] = "Instruction privilege error",
49     [EXCCODE_FPE] = "Floating Point Exception",
50     [EXCCODE_DBP] = "Debug breakpoint",
51 };
52
53 const char *loongarch_exception_name(int32_t exception)
54 {
55     assert(excp_names[exception]);
56     return excp_names[exception];
57 }
58
59 void G_NORETURN do_raise_exception(CPULoongArchState *env,
60                                    uint32_t exception,
61                                    uintptr_t pc)
62 {
63     CPUState *cs = env_cpu(env);
64
65     qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
66                   __func__,
67                   exception,
68                   loongarch_exception_name(exception));
69     cs->exception_index = exception;
70
71     cpu_loop_exit_restore(cs, pc);
72 }
73
74 static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
75 {
76     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
77     CPULoongArchState *env = &cpu->env;
78
79     env->pc = value;
80 }
81
82 #ifdef CONFIG_TCG
83 static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
84                                               const TranslationBlock *tb)
85 {
86     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
87     CPULoongArchState *env = &cpu->env;
88
89     env->pc = tb->pc;
90 }
91 #endif /* CONFIG_TCG */
92
93 static void loongarch_la464_initfn(Object *obj)
94 {
95     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
96     CPULoongArchState *env = &cpu->env;
97     int i;
98
99     for (i = 0; i < 21; i++) {
100         env->cpucfg[i] = 0x0;
101     }
102
103     env->cpucfg[0] = 0x14c010;  /* PRID */
104
105     uint32_t data = 0;
106     data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
107     data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
108     data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
109     data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
110     data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
111     data = FIELD_DP32(data, CPUCFG1, UAL, 1);
112     data = FIELD_DP32(data, CPUCFG1, RI, 1);
113     data = FIELD_DP32(data, CPUCFG1, EP, 1);
114     data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
115     data = FIELD_DP32(data, CPUCFG1, HP, 1);
116     data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
117     env->cpucfg[1] = data;
118
119     data = 0;
120     data = FIELD_DP32(data, CPUCFG2, FP, 1);
121     data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
122     data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
123     data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
124     data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
125     data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
126     data = FIELD_DP32(data, CPUCFG2, LAM, 1);
127     env->cpucfg[2] = data;
128
129     env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
130
131     data = 0;
132     data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
133     data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
134     env->cpucfg[5] = data;
135
136     data = 0;
137     data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
138     data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
139     data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
140     data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
141     data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
142     data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
143     data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
144     data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
145     env->cpucfg[16] = data;
146
147     data = 0;
148     data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 3);
149     data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 8);
150     data = FIELD_DP32(data, CPUCFG17, L1IU_SIZE, 6);
151     env->cpucfg[17] = data;
152
153     data = 0;
154     data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 3);
155     data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 8);
156     data = FIELD_DP32(data, CPUCFG18, L1D_SIZE, 6);
157     env->cpucfg[18] = data;
158
159     data = 0;
160     data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 15);
161     data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 8);
162     data = FIELD_DP32(data, CPUCFG19, L2IU_SIZE, 6);
163     env->cpucfg[19] = data;
164
165     data = 0;
166     data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 15);
167     data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 14);
168     data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 6);
169     env->cpucfg[20] = data;
170 }
171
172 static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
173 {
174     const char *typename = object_class_get_name(OBJECT_CLASS(data));
175
176     qemu_printf("%s\n", typename);
177 }
178
179 void loongarch_cpu_list(void)
180 {
181     GSList *list;
182     list = object_class_get_list_sorted(TYPE_LOONGARCH_CPU, false);
183     g_slist_foreach(list, loongarch_cpu_list_entry, NULL);
184     g_slist_free(list);
185 }
186
187 static void loongarch_cpu_reset(DeviceState *dev)
188 {
189     CPUState *cs = CPU(dev);
190     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
191     LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
192     CPULoongArchState *env = &cpu->env;
193
194     lacc->parent_reset(dev);
195
196     env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
197     env->fcsr0 = 0x0;
198
199     cs->exception_index = -1;
200 }
201
202 static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
203 {
204     info->print_insn = print_insn_loongarch;
205 }
206
207 static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
208 {
209     CPUState *cs = CPU(dev);
210     LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
211     Error *local_err = NULL;
212
213     cpu_exec_realizefn(cs, &local_err);
214     if (local_err != NULL) {
215         error_propagate(errp, local_err);
216         return;
217     }
218
219     cpu_reset(cs);
220     qemu_init_vcpu(cs);
221
222     lacc->parent_realize(dev, errp);
223 }
224
225 static void loongarch_cpu_init(Object *obj)
226 {
227     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
228
229     cpu_set_cpustate_pointers(cpu);
230 }
231
232 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
233 {
234     ObjectClass *oc;
235     char *typename;
236
237     typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
238     oc = object_class_by_name(typename);
239     g_free(typename);
240     return oc;
241 }
242
243 void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
244 {
245     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
246     CPULoongArchState *env = &cpu->env;
247     int i;
248
249     qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
250     qemu_fprintf(f, " FCSR0 0x%08x  fp_status 0x%02x\n", env->fcsr0,
251                  get_float_exception_flags(&env->fp_status));
252
253     /* gpr */
254     for (i = 0; i < 32; i++) {
255         if ((i & 3) == 0) {
256             qemu_fprintf(f, " GPR%02d:", i);
257         }
258         qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
259         if ((i & 3) == 3) {
260             qemu_fprintf(f, "\n");
261         }
262     }
263
264     /* fpr */
265     if (flags & CPU_DUMP_FPU) {
266         for (i = 0; i < 32; i++) {
267             qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]);
268             if ((i & 3) == 3) {
269                 qemu_fprintf(f, "\n");
270             }
271         }
272     }
273 }
274
275 #ifdef CONFIG_TCG
276 #include "hw/core/tcg-cpu-ops.h"
277
278 static struct TCGCPUOps loongarch_tcg_ops = {
279     .initialize = loongarch_translate_init,
280     .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
281 };
282 #endif /* CONFIG_TCG */
283
284 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
285 {
286     LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
287     CPUClass *cc = CPU_CLASS(c);
288     DeviceClass *dc = DEVICE_CLASS(c);
289
290     device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
291                                     &lacc->parent_realize);
292     device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset);
293
294     cc->class_by_name = loongarch_cpu_class_by_name;
295     cc->dump_state = loongarch_cpu_dump_state;
296     cc->set_pc = loongarch_cpu_set_pc;
297     cc->disas_set_info = loongarch_cpu_disas_set_info;
298 #ifdef CONFIG_TCG
299     cc->tcg_ops = &loongarch_tcg_ops;
300 #endif
301 }
302
303 #define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
304     { \
305         .parent = TYPE_LOONGARCH_CPU, \
306         .instance_init = initfn, \
307         .name = LOONGARCH_CPU_TYPE_NAME(model), \
308     }
309
310 static const TypeInfo loongarch_cpu_type_infos[] = {
311     {
312         .name = TYPE_LOONGARCH_CPU,
313         .parent = TYPE_CPU,
314         .instance_size = sizeof(LoongArchCPU),
315         .instance_init = loongarch_cpu_init,
316
317         .abstract = true,
318         .class_size = sizeof(LoongArchCPUClass),
319         .class_init = loongarch_cpu_class_init,
320     },
321     DEFINE_LOONGARCH_CPU_TYPE("la464", loongarch_la464_initfn),
322 };
323
324 DEFINE_TYPES(loongarch_cpu_type_infos)
This page took 0.032518 seconds and 2 git commands to generate.