master
c 991 lines 29.3 KB
Raw
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 "system/qtest.h"
14 #include "system/tcg.h"
15 #include "system/kvm.h"
16 #include "kvm/kvm_loongarch.h"
17 #include "hw/core/qdev-properties.h"
18 #include "exec/translation-block.h"
19 #include "cpu.h"
20 #include "cpu-mmu.h"
21 #include "internals.h"
22 #include "fpu/softfloat-helpers.h"
23 #include "csr.h"
24 #ifndef CONFIG_USER_ONLY
25 #include "system/reset.h"
26 #endif
27 #include "vec.h"
28 #ifdef CONFIG_KVM
29 #include <linux/kvm.h>
30 #endif
31 #include "tcg/tcg_loongarch.h"
32 #include "disas/capstone.h"
33
34 const char * const regnames[32] = {
35 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
36 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
37 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
38 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
39 };
40
41 const char * const fregnames[32] = {
42 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
43 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
44 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
45 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
46 };
47
48 static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
49 {
50 set_pc(cpu_env(cs), value);
51 }
52
53 static vaddr loongarch_cpu_get_pc(CPUState *cs)
54 {
55 return cpu_env(cs)->pc;
56 }
57
58 #ifndef CONFIG_USER_ONLY
59 #include "hw/loongarch/virt.h"
60
61 void loongarch_cpu_update_irq(LoongArchCPU *cpu, uint64_t old)
62 {
63 CPULoongArchState *env = &cpu->env;
64 CPUState *cs = CPU(cpu);
65 CPUSysState *sys = env_sys(env);
66
67 if (FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS)) {
68 if (!FIELD_EX64(old, CSR_ESTAT, IS)) {
69 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
70 }
71 } else {
72 if (FIELD_EX64(old, CSR_ESTAT, IS)) {
73 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
74 }
75 }
76 }
77
78 void loongarch_cpu_set_irq(void *opaque, int irq, int level)
79 {
80 LoongArchCPU *cpu = opaque;
81 CPULoongArchState *env = &cpu->env;
82 CPUSysState *sys = env_sys(env);
83 uint64_t old;
84
85 if (irq < 0 || irq >= N_IRQS) {
86 return;
87 }
88
89 if (kvm_enabled()) {
90 kvm_loongarch_set_interrupt(cpu, irq, level);
91 } else if (tcg_enabled()) {
92 old = sys->CSR_ESTAT;
93 sys->CSR_ESTAT = deposit64(sys->CSR_ESTAT, irq, 1, level != 0);
94 loongarch_cpu_update_irq(cpu, old);
95 }
96 }
97
98 /* Check if there is pending and not masked out interrupt */
99 bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
100 {
101 uint32_t pending;
102 uint32_t status;
103 CPUSysState *sys = env_sys(env);
104
105 pending = FIELD_EX64(sys->CSR_ESTAT, CSR_ESTAT, IS);
106 status = FIELD_EX64(sys->CSR_ECFG, CSR_ECFG, LIE);
107
108 return (pending & status) != 0;
109 }
110 #endif
111
112 #ifndef CONFIG_USER_ONLY
113 bool loongarch_cpu_has_work(CPUState *cs)
114 {
115 bool has_work = false;
116
117 if (cpu_test_interrupt(cs, CPU_INTERRUPT_HARD) &&
118 cpu_loongarch_hw_interrupts_pending(cpu_env(cs))) {
119 has_work = true;
120 }
121
122 return has_work;
123 }
124 #endif /* !CONFIG_USER_ONLY */
125
126 static void loongarch_la464_init_csr(DeviceState *dev)
127 {
128 #ifndef CONFIG_USER_ONLY
129 static bool initialized;
130 LoongArchCPU *cpu = LOONGARCH_CPU(dev);
131 CPULoongArchState *env = &cpu->env;
132 CPUSysState *sys = env_sys(env);
133 int i, num;
134
135 if (!initialized) {
136 initialized = true;
137 num = FIELD_EX64(sys->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM);
138 for (i = num; i < 16; i++) {
139 set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED);
140 }
141 set_csr_flag(LOONGARCH_CSR_IMPCTL1, CSRFL_UNUSED);
142 set_csr_flag(LOONGARCH_CSR_IMPCTL2, CSRFL_UNUSED);
143 set_csr_flag(LOONGARCH_CSR_MERRCTL, CSRFL_UNUSED);
144 set_csr_flag(LOONGARCH_CSR_MERRINFO1, CSRFL_UNUSED);
145 set_csr_flag(LOONGARCH_CSR_MERRINFO2, CSRFL_UNUSED);
146 set_csr_flag(LOONGARCH_CSR_MERRENTRY, CSRFL_UNUSED);
147 set_csr_flag(LOONGARCH_CSR_MERRERA, CSRFL_UNUSED);
148 set_csr_flag(LOONGARCH_CSR_MERRSAVE, CSRFL_UNUSED);
149 set_csr_flag(LOONGARCH_CSR_CTAG, CSRFL_UNUSED);
150
151 for (i = env->perf_event_num; i < MAX_PERF_EVENTS; i++) {
152 set_csr_flag(LOONGARCH_CSR_PERFCTRL(i), CSRFL_UNUSED);
153 set_csr_flag(LOONGARCH_CSR_PERFCNTR(i), CSRFL_UNUSED);
154 }
155 }
156 #endif
157 }
158
159 static bool loongarch_get_lsx(Object *obj, Error **errp)
160 {
161 return LOONGARCH_CPU(obj)->lsx != ON_OFF_AUTO_OFF;
162 }
163
164 static void loongarch_set_lsx(Object *obj, bool value, Error **errp)
165 {
166 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
167 uint32_t val;
168
169 cpu->lsx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
170 if (cpu->lsx == ON_OFF_AUTO_OFF) {
171 cpu->lasx = ON_OFF_AUTO_OFF;
172 if (cpu->lasx == ON_OFF_AUTO_ON) {
173 error_setg(errp, "Failed to disable LSX since LASX is enabled");
174 return;
175 }
176 }
177
178 if (kvm_enabled()) {
179 /* kvm feature detection in function kvm_arch_init_vcpu */
180 return;
181 }
182
183 /* LSX feature detection in TCG mode */
184 val = cpu->env.cpucfg[2];
185 if (cpu->lsx == ON_OFF_AUTO_ON) {
186 if (FIELD_EX32(val, CPUCFG2, LSX) == 0) {
187 error_setg(errp, "Failed to enable LSX in TCG mode");
188 return;
189 }
190 } else {
191 cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, 0);
192 val = cpu->env.cpucfg[2];
193 }
194
195 cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LSX, value);
196 }
197
198 static bool loongarch_get_lasx(Object *obj, Error **errp)
199 {
200 return LOONGARCH_CPU(obj)->lasx != ON_OFF_AUTO_OFF;
201 }
202
203 static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
204 {
205 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
206 uint32_t val;
207
208 cpu->lasx = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
209 if ((cpu->lsx == ON_OFF_AUTO_OFF) && (cpu->lasx == ON_OFF_AUTO_ON)) {
210 error_setg(errp, "Failed to enable LASX since lSX is disabled");
211 return;
212 }
213
214 if (kvm_enabled()) {
215 /* kvm feature detection in function kvm_arch_init_vcpu */
216 return;
217 }
218
219 /* LASX feature detection in TCG mode */
220 val = cpu->env.cpucfg[2];
221 if (cpu->lasx == ON_OFF_AUTO_ON) {
222 if (FIELD_EX32(val, CPUCFG2, LASX) == 0) {
223 error_setg(errp, "Failed to enable LASX in TCG mode");
224 return;
225 }
226 }
227
228 cpu->env.cpucfg[2] = FIELD_DP32(val, CPUCFG2, LASX, value);
229 }
230
231 static bool loongarch_get_msgint(Object *obj, Error **errp)
232 {
233 return LOONGARCH_CPU(obj)->msgint != ON_OFF_AUTO_OFF;
234 }
235
236 static void loongarch_set_msgint(Object *obj, bool value, Error **errp)
237 {
238 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
239
240 cpu->msgint = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
241
242 if (kvm_enabled()) {
243 /* kvm feature detection in function kvm_arch_init_vcpu */
244 return;
245 }
246
247 cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, value);
248 }
249
250 static bool loongarch_get_ptw(Object *obj, Error **errp)
251 {
252 return LOONGARCH_CPU(obj)->ptw != ON_OFF_AUTO_OFF;
253 }
254
255 static void loongarch_set_ptw(Object *obj, bool value, Error **errp)
256 {
257 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
258
259 cpu->ptw = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
260
261 if (kvm_enabled()) {
262 /* kvm feature detection in function kvm_arch_init_vcpu */
263 return;
264 }
265
266 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, HPTW, value);
267 }
268
269 static void loongarch_cpu_post_init(Object *obj)
270 {
271 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
272
273 cpu->lbt = ON_OFF_AUTO_OFF;
274 cpu->pmu = ON_OFF_AUTO_OFF;
275 cpu->lsx = ON_OFF_AUTO_AUTO;
276 cpu->lasx = ON_OFF_AUTO_AUTO;
277 object_property_add_bool(obj, "lsx", loongarch_get_lsx,
278 loongarch_set_lsx);
279 object_property_add_bool(obj, "lasx", loongarch_get_lasx,
280 loongarch_set_lasx);
281 object_property_add_bool(obj, "msgint", loongarch_get_msgint,
282 loongarch_set_msgint);
283 object_property_add_bool(obj, "ptw", loongarch_get_ptw,
284 loongarch_set_ptw);
285 /* lbt is enabled only in kvm mode, not supported in tcg mode */
286
287 if (kvm_enabled()) {
288 kvm_loongarch_cpu_post_init(cpu);
289 }
290 }
291
292 static void loongarch_la464_initfn(Object *obj)
293 {
294 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
295 CPULoongArchState *env = &cpu->env;
296 CPUSysState *sys;
297 uint32_t data = 0, field;
298 int i;
299
300 set_sys_state(env, &env->sys_states[0]);
301 for (i = 0; i < 21; i++) {
302 env->cpucfg[i] = 0x0;
303 }
304
305 cpu->dtb_compatible = "loongarch,Loongson-3A5000";
306 data = FIELD_DP32(data, CPUCFG0, PRID, 0x10);
307 data = FIELD_DP32(data, CPUCFG0, SERID, PRID_SERIES_LA464);
308 data = FIELD_DP32(data, CPUCFG0, VENID, PRID_VENDOR_LOONGSON);
309 env->cpucfg[0] = data;
310 memccpy((void *)&env->vendor_id, CPU_VENDOR_LOONGSON, 0, 8);
311 memccpy((void *)&env->cpu_id, CPU_MODEL_3A5000, 0, 8);
312
313 data = 0;
314 data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
315 data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
316 data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
317 if (kvm_enabled()) {
318 /* GPA address width of VM is 47, field value is 47 - 1 */
319 field = 0x2e;
320 } else {
321 field = 0x2f; /* 48 bit - 1 */
322 }
323 data = FIELD_DP32(data, CPUCFG1, PALEN, field);
324 data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
325 data = FIELD_DP32(data, CPUCFG1, UAL, 1);
326 data = FIELD_DP32(data, CPUCFG1, RI, 1);
327 data = FIELD_DP32(data, CPUCFG1, EP, 1);
328 data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
329 data = FIELD_DP32(data, CPUCFG1, HP, 1);
330 data = FIELD_DP32(data, CPUCFG1, CRC, 1);
331 env->cpucfg[1] = data;
332
333 data = 0;
334 data = FIELD_DP32(data, CPUCFG2, FP, 1);
335 data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
336 data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
337 data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
338 data = FIELD_DP32(data, CPUCFG2, LSX, 1),
339 data = FIELD_DP32(data, CPUCFG2, LASX, 1),
340 data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
341 data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
342 data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
343 data = FIELD_DP32(data, CPUCFG2, LAM, 1);
344 env->cpucfg[2] = data;
345
346 data = 0;
347 data = FIELD_DP32(data, CPUCFG3, CCDMA, 1);
348 data = FIELD_DP32(data, CPUCFG3, UCACC, 1);
349 data = FIELD_DP32(data, CPUCFG3, LLEXC, 1);
350 data = FIELD_DP32(data, CPUCFG3, SCDLY, 1);
351 data = FIELD_DP32(data, CPUCFG3, LLDBAR, 1);
352 data = FIELD_DP32(data, CPUCFG3, ITLBHMC, 1);
353 data = FIELD_DP32(data, CPUCFG3, ICHMC, 1);
354 data = FIELD_DP32(data, CPUCFG3, SPW_LVL, 4);
355 data = FIELD_DP32(data, CPUCFG3, SPW_HP_HF, 1);
356 if (kvm_enabled()) {
357 data = FIELD_DP32(data, CPUCFG3, RVA, 1);
358 data = FIELD_DP32(data, CPUCFG3, RVAMAX, 7);
359 }
360 env->cpucfg[3] = data;
361
362 env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
363
364 data = 0;
365 data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
366 data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
367 env->cpucfg[5] = data;
368
369 data = 0;
370 data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
371 data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
372 data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
373 data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
374 data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
375 data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
376 data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
377 data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
378 env->cpucfg[16] = data;
379
380 data = 0;
381 data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 3);
382 data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 8);
383 data = FIELD_DP32(data, CPUCFG17, L1IU_SIZE, 6);
384 env->cpucfg[17] = data;
385
386 data = 0;
387 data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 3);
388 data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 8);
389 data = FIELD_DP32(data, CPUCFG18, L1D_SIZE, 6);
390 env->cpucfg[18] = data;
391
392 data = 0;
393 data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 15);
394 data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 8);
395 data = FIELD_DP32(data, CPUCFG19, L2IU_SIZE, 6);
396 env->cpucfg[19] = data;
397
398 data = 0;
399 data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 15);
400 data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 14);
401 data = FIELD_DP32(data, CPUCFG20, L3IU_SIZE, 6);
402 env->cpucfg[20] = data;
403
404 sys = env_sys(env);
405 sys->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
406
407 sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM, 8);
408 sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, TIMER_BITS, 0x2f);
409 sys->CSR_PRCFG1 = FIELD_DP64(sys->CSR_PRCFG1, CSR_PRCFG1, VSMAX, 7);
410
411 sys->CSR_PRCFG2 = 0x3ffff000;
412
413 sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
414 sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
415 sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
416 sys->CSR_PRCFG3 = FIELD_DP64(sys->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
417
418 cpu->msgint = ON_OFF_AUTO_OFF;
419 cpu->ptw = ON_OFF_AUTO_OFF;
420 loongarch_cpu_post_init(obj);
421 }
422
423 static void loongarch_la132_initfn(Object *obj)
424 {
425 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
426 CPULoongArchState *env = &cpu->env;
427 uint32_t data = 0;
428 int i;
429
430 set_sys_state(env, &env->sys_states[0]);
431 for (i = 0; i < 21; i++) {
432 env->cpucfg[i] = 0x0;
433 }
434
435 cpu->dtb_compatible = "loongarch,Loongson-1C103";
436 data = FIELD_DP32(data, CPUCFG0, PRID, 0x42);
437 data = FIELD_DP32(data, CPUCFG0, SERID, PRID_SERIES_LA132);
438 data = FIELD_DP32(data, CPUCFG0, VENID, PRID_VENDOR_LOONGSON);
439 env->cpucfg[0] = data;
440 memccpy((void *)&env->vendor_id, CPU_VENDOR_LOONGSON, 0, 8);
441 memccpy((void *)&env->cpu_id, CPU_MODEL_1C101, 0, 8);
442
443 data = 0;
444 data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */
445 data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
446 data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
447 data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */
448 data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */
449 data = FIELD_DP32(data, CPUCFG1, UAL, 1);
450 data = FIELD_DP32(data, CPUCFG1, RI, 0);
451 data = FIELD_DP32(data, CPUCFG1, EP, 0);
452 data = FIELD_DP32(data, CPUCFG1, RPLV, 0);
453 data = FIELD_DP32(data, CPUCFG1, HP, 1);
454 data = FIELD_DP32(data, CPUCFG1, CRC, 1);
455 env->cpucfg[1] = data;
456 cpu->msgint = ON_OFF_AUTO_OFF;
457 cpu->ptw = ON_OFF_AUTO_OFF;
458 }
459
460 static void loongarch_max_initfn(Object *obj)
461 {
462 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
463 /* '-cpu max': use it for max supported CPU features */
464 loongarch_la464_initfn(obj);
465
466 cpu->ptw = ON_OFF_AUTO_AUTO;
467 if (kvm_enabled()){
468 cpu->msgint=ON_OFF_AUTO_OFF;
469 }
470 if (tcg_enabled()) {
471 uint32_t data = cpu->env.cpucfg[2];
472 data = FIELD_DP32(data, CPUCFG2, HPTW, 1);
473 /* Enable LA v1.1 instructions */
474 data = FIELD_DP32(data, CPUCFG2, FRECIPE, 1);
475 data = FIELD_DP32(data, CPUCFG2, LAM_BH, 1);
476 data = FIELD_DP32(data, CPUCFG2, LAMCAS, 1);
477 data = FIELD_DP32(data, CPUCFG2, LLACQ_SCREL, 1);
478 data = FIELD_DP32(data, CPUCFG2, SCQ, 1);
479 cpu->env.cpucfg[2] = data;
480
481 data = cpu->env.cpucfg[3];
482 data = FIELD_DP32(data, CPUCFG3, DBAR_HINTS, 1);
483 cpu->env.cpucfg[3] = data;
484 cpu->env.cpucfg[1] = FIELD_DP32(cpu->env.cpucfg[1], CPUCFG1, MSG_INT, 1);
485 cpu->msgint = ON_OFF_AUTO_AUTO;
486 }
487 }
488
489 #if defined(CONFIG_KVM)
490 static int read_cpuinfo(const char *field, char *value, int len)
491 {
492 FILE *f;
493 int ret = -1;
494 int field_len = strlen(field);
495 char line[512];
496
497 f = fopen("/proc/cpuinfo", "r");
498 if (!f) {
499 return -1;
500 }
501
502 do {
503 if (!fgets(line, sizeof(line), f)) {
504 break;
505 }
506 if (!strncmp(line, field, field_len)) {
507 strncpy(value, line, len);
508 ret = 0;
509 break;
510 }
511 } while (*line);
512
513 fclose(f);
514
515 return ret;
516 }
517
518 static uint64_t get_host_cpu_model(void)
519 {
520 char line[512];
521 char *ns;
522 static uint64_t cpuid;
523
524 if (cpuid) {
525 return cpuid;
526 }
527
528 if (read_cpuinfo("Model Name", line, sizeof(line))) {
529 return 0;
530 }
531
532 ns = strchr(line, ':');
533 if (!ns) {
534 return 0;
535 }
536
537 ns = strstr(ns, "Loongson-");
538 if (!ns) {
539 return 0;
540 }
541
542 ns += strlen("Loongson-");
543 memccpy((void *)&cpuid, ns, 0, 8);
544 return cpuid;
545 }
546
547 static uint32_t get_host_cpucfg(int number)
548 {
549 unsigned int data = 0;
550
551 #ifdef __loongarch__
552 asm volatile("cpucfg %[val], %[reg]"
553 : [val] "=r" (data)
554 : [reg] "r" (number)
555 : "memory");
556 #endif
557
558 return data;
559 }
560
561 static void loongarch_host_initfn(Object *obj)
562 {
563 uint32_t data, cpucfg, field;
564 uint64_t cpuid;
565 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
566
567 loongarch_max_initfn(obj);
568 data = get_host_cpucfg(0);
569 if (data) {
570 cpu->env.cpucfg[0] = data;
571 }
572
573 /*
574 * There is no exception in KVM hypervisor when these intructions are
575 * executed if HW support, KVM hypervisor cannot control this.
576 *
577 * Set cpucfg bits which cannot be controlled by KVM hypervisor.
578 */
579 data = get_host_cpucfg(2);
580 cpucfg = cpu->env.cpucfg[2];
581 field = FIELD_EX32(data, CPUCFG2, FRECIPE);
582 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, FRECIPE, field);
583 field = FIELD_EX32(data, CPUCFG2, DIV32);
584 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, DIV32, field);
585 field = FIELD_EX32(data, CPUCFG2, LAM_BH);
586 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, LAM_BH, field);
587 field = FIELD_EX32(data, CPUCFG2, LAMCAS);
588 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, LAMCAS, field);
589 field = FIELD_EX32(data, CPUCFG2, LLACQ_SCREL);
590 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, LLACQ_SCREL, field);
591 field = FIELD_EX32(data, CPUCFG2, SCQ);
592 cpucfg = FIELD_DP32(cpucfg, CPUCFG2, SCQ, field);
593 cpu->env.cpucfg[2] = cpucfg;
594
595 data = get_host_cpucfg(3);
596 cpucfg = cpu->env.cpucfg[3];
597 field = FIELD_EX32(data, CPUCFG3, DBAR_HINTS);
598 cpucfg = FIELD_DP32(cpucfg, CPUCFG3, DBAR_HINTS, field);
599 field = FIELD_EX32(data, CPUCFG3, ALDORDER_STA);
600 cpucfg = FIELD_DP32(cpucfg, CPUCFG3, ALDORDER_STA, field);
601 field = FIELD_EX32(data, CPUCFG3, ASTORDER_STA);
602 cpucfg = FIELD_DP32(cpucfg, CPUCFG3, ASTORDER_STA, field);
603 field = FIELD_EX32(data, CPUCFG3, SLDORDER_STA);
604 cpucfg = FIELD_DP32(cpucfg, CPUCFG3, SLDORDER_STA, field);
605 cpu->env.cpucfg[3] = cpucfg;
606
607 cpuid = get_host_cpu_model();
608 if (cpuid) {
609 cpu->env.cpu_id = cpuid;
610 }
611 }
612 #endif
613
614 static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
615 {
616 uint8_t tlb_ps;
617 CPUState *cs = CPU(obj);
618 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
619 CPULoongArchState *env = cpu_env(cs);
620 CPUSysState *sys = env_sys(env);
621
622 if (lacc->parent_phases.hold) {
623 lacc->parent_phases.hold(obj, type);
624 }
625
626 #ifdef CONFIG_TCG
627 env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
628
629 if (is_la64(env)) {
630 env->hw_pte_mask = MAKE_64BIT_MASK(0, 9) |
631 R_TLBENTRY_64_PPN_MASK |
632 R_TLBENTRY_64_NR_MASK |
633 R_TLBENTRY_64_NX_MASK |
634 R_TLBENTRY_64_RPLV_MASK;
635 } else {
636 env->hw_pte_mask = MAKE_64BIT_MASK(0, 9) |
637 R_TLBENTRY_32_PPN_MASK;
638 }
639 #endif
640 env->fcsr0 = 0x0;
641
642 int n;
643 /* Set csr registers value after reset, see the manual 6.4. */
644 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PLV, 0);
645 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, 0);
646 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
647 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PG, 0);
648 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATF, 0);
649 sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATM, 0);
650
651 sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, FPE, 0);
652 sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, SXE, 0);
653 sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, ASXE, 0);
654 sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, BTE, 0);
655
656 sys->CSR_MISC = 0;
657
658 sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, VS, 0);
659 sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, LIE, 0);
660
661 sys->CSR_ESTAT = sys->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
662 sys->CSR_RVACFG = FIELD_DP64(sys->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
663 sys->CSR_CPUID = cs->cpu_index;
664 sys->CSR_TCFG = FIELD_DP64(sys->CSR_TCFG, CSR_TCFG, EN, 0);
665 sys->CSR_LLBCTL = FIELD_DP64(sys->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
666 sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
667 sys->CSR_MERRCTL = FIELD_DP64(sys->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
668 sys->CSR_TID = cs->cpu_index;
669 /*
670 * Workaround for edk2-stable202408, CSR PGD register is set only if
671 * its value is equal to zero for boot cpu, it causes reboot issue.
672 *
673 * Here clear CSR registers relative with TLB.
674 */
675 sys->CSR_PGDH = 0;
676 sys->CSR_PGDL = 0;
677 sys->CSR_PWCH = 0;
678 sys->CSR_EENTRY = 0;
679 sys->CSR_TLBRENTRY = 0;
680 sys->CSR_MERRENTRY = 0;
681 /* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */
682 if (sys->CSR_PRCFG2 == 0) {
683 sys->CSR_PRCFG2 = 0x3fffff000;
684 }
685 tlb_ps = ctz32(sys->CSR_PRCFG2);
686 sys->CSR_STLBPS = FIELD_DP64(sys->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps);
687 sys->CSR_PWCL = FIELD_DP64(sys->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps);
688 for (n = 0; n < 4; n++) {
689 sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV0, 0);
690 sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV1, 0);
691 sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV2, 0);
692 sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV3, 0);
693 }
694
695 #ifndef CONFIG_USER_ONLY
696 env->pc = 0x1c000000;
697 #ifdef CONFIG_TCG
698 memset(env->tlb, 0, sizeof(env->tlb));
699 #endif
700 if (kvm_enabled()) {
701 kvm_arch_reset_vcpu(cs);
702 }
703 #endif
704
705 #ifdef CONFIG_TCG
706 restore_fp_status(env);
707 #endif
708 cs->exception_index = -1;
709 }
710
711 static void loongarch_cpu_disas_set_info(const CPUState *cs,
712 disassemble_info *info)
713 {
714 CPULoongArchState *env = cpu_env((CPUState *)cs);
715
716 info->endian = BFD_ENDIAN_LITTLE;
717 info->print_insn = print_insn_loongarch;
718
719 info->cap_arch = CS_ARCH_LOONGARCH;
720 info->cap_insn_unit = 4;
721 info->cap_insn_split = 4;
722 info->cap_mode = is_la64(env) ? CS_MODE_LOONGARCH64 : CS_MODE_LOONGARCH32;
723 }
724
725 static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
726 {
727 CPUState *cs = CPU(dev);
728 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
729 Error *local_err = NULL;
730
731 cpu_common_realize(cs, &local_err);
732 if (local_err != NULL) {
733 error_propagate(errp, local_err);
734 return;
735 }
736
737 loongarch_cpu_register_gdb_regs_for_features(cs);
738
739 qemu_init_vcpu(cs);
740 cpu_reset(cs);
741 loongarch_la464_init_csr(dev);
742
743 lacc->parent_realize(dev, errp);
744 }
745
746 static void loongarch_cpu_unrealizefn(DeviceState *dev)
747 {
748 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
749
750 #ifndef CONFIG_USER_ONLY
751 cpu_remove_sync(CPU(dev));
752 #endif
753
754 lacc->parent_unrealize(dev);
755 }
756
757 static void loongarch_cpu_init(Object *obj)
758 {
759 #ifndef CONFIG_USER_ONLY
760 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
761
762 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
763 #ifdef CONFIG_TCG
764 timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
765 &loongarch_constant_timer_cb, cpu);
766 #endif
767 #endif
768 }
769
770 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
771 {
772 ObjectClass *oc;
773
774 oc = object_class_by_name(cpu_model);
775 if (!oc) {
776 g_autofree char *typename
777 = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
778 oc = object_class_by_name(typename);
779 }
780
781 return oc;
782 }
783
784 static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f)
785 {
786 #ifndef CONFIG_USER_ONLY
787 CPULoongArchState *env = cpu_env(cs);
788 const CSRInfo *csr_info;
789 int64_t *addr;
790 int i, j, len, col = 0;
791
792 qemu_fprintf(f, "\n");
793
794 /* Dump all generic CSR register */
795 for (i = 0; i < LOONGARCH_CSR_DBG; i++) {
796 csr_info = get_csr(i);
797 if (!csr_info || (csr_info->flags & CSRFL_UNUSED)) {
798 if (i == (col + 3)) {
799 qemu_fprintf(f, "\n");
800 }
801
802 continue;
803 }
804
805 if ((i > (col + 3)) || (i == col)) {
806 col = i & ~3;
807 qemu_fprintf(f, " CSR%03d:", col);
808 }
809
810 addr = (void *)env + get_csr_offset(csr_info, 0);
811 qemu_fprintf(f, " %s ", csr_info->name);
812 len = strlen(csr_info->name);
813 for (; len < 6; len++) {
814 qemu_fprintf(f, " ");
815 }
816
817 qemu_fprintf(f, "%" PRIx64, *addr);
818 j = find_last_bit((void *)addr, BITS_PER_LONG) & (BITS_PER_LONG - 1);
819 len += j / 4 + 1;
820 for (; len < 22; len++) {
821 qemu_fprintf(f, " ");
822 }
823
824 if (i == (col + 3)) {
825 qemu_fprintf(f, "\n");
826 }
827 }
828 qemu_fprintf(f, "\n");
829 #endif
830 }
831
832 static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
833 {
834 CPULoongArchState *env = cpu_env(cs);
835 int i;
836
837 qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
838 qemu_fprintf(f, " FCSR0 0x%08x\n", env->fcsr0);
839
840 /* gpr */
841 for (i = 0; i < 32; i++) {
842 if ((i & 3) == 0) {
843 qemu_fprintf(f, " GPR%02d:", i);
844 }
845 qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
846 if ((i & 3) == 3) {
847 qemu_fprintf(f, "\n");
848 }
849 }
850
851 /* csr */
852 loongarch_cpu_dump_csr(cs, f);
853
854 /* fpr */
855 if (flags & CPU_DUMP_FPU) {
856 for (i = 0; i < 32; i++) {
857 qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i].vreg.D(0));
858 if ((i & 3) == 3) {
859 qemu_fprintf(f, "\n");
860 }
861 }
862 }
863 }
864
865 #ifndef CONFIG_USER_ONLY
866 #include "hw/core/sysemu-cpu-ops.h"
867
868 static const struct SysemuCPUOps loongarch_sysemu_ops = {
869 .has_work = loongarch_cpu_has_work,
870 .write_elf64_note = loongarch_cpu_write_elf64_note,
871 .get_phys_addr_debug = loongarch_cpu_get_phys_addr_debug,
872 };
873
874 static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
875 {
876 LoongArchCPU *cpu = LOONGARCH_CPU(cs);
877
878 return cpu->phy_id;
879 }
880 #endif
881
882 static const Property loongarch_cpu_properties[] = {
883 DEFINE_PROP_INT32("socket-id", LoongArchCPU, socket_id, 0),
884 DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, 0),
885 DEFINE_PROP_INT32("thread-id", LoongArchCPU, thread_id, 0),
886 DEFINE_PROP_INT32("node-id", LoongArchCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
887 };
888
889 static void loongarch_cpu_class_init(ObjectClass *c, const void *data)
890 {
891 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
892 CPUClass *cc = CPU_CLASS(c);
893 DeviceClass *dc = DEVICE_CLASS(c);
894 ResettableClass *rc = RESETTABLE_CLASS(c);
895
896 device_class_set_props(dc, loongarch_cpu_properties);
897 device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
898 &lacc->parent_realize);
899 device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
900 &lacc->parent_unrealize);
901 resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL,
902 &lacc->parent_phases);
903
904 cc->class_by_name = loongarch_cpu_class_by_name;
905 cc->dump_state = loongarch_cpu_dump_state;
906 cc->set_pc = loongarch_cpu_set_pc;
907 cc->get_pc = loongarch_cpu_get_pc;
908 #ifndef CONFIG_USER_ONLY
909 cc->get_arch_id = loongarch_cpu_get_arch_id;
910 dc->vmsd = &vmstate_loongarch_cpu;
911 cc->sysemu_ops = &loongarch_sysemu_ops;
912 #endif
913 cc->disas_set_info = loongarch_cpu_disas_set_info;
914 cc->gdb_read_register = loongarch_cpu_gdb_read_register;
915 cc->gdb_write_register = loongarch_cpu_gdb_write_register;
916 cc->gdb_stop_before_watchpoint = true;
917
918 #ifdef CONFIG_TCG
919 cc->tcg_ops = &loongarch_tcg_ops;
920 #endif
921 dc->user_creatable = true;
922 }
923
924 static const gchar *loongarch32_gdb_arch_name(CPUState *cs)
925 {
926 return "loongarch32";
927 }
928
929 static void loongarch32_cpu_class_init(ObjectClass *c, const void *data)
930 {
931 CPUClass *cc = CPU_CLASS(c);
932
933 cc->gdb_core_xml_file = "loongarch-base32.xml";
934 cc->gdb_arch_name = loongarch32_gdb_arch_name;
935 }
936
937 static const gchar *loongarch64_gdb_arch_name(CPUState *cs)
938 {
939 return "loongarch64";
940 }
941
942 static void loongarch64_cpu_class_init(ObjectClass *c, const void *data)
943 {
944 CPUClass *cc = CPU_CLASS(c);
945
946 cc->gdb_core_xml_file = "loongarch-base64.xml";
947 cc->gdb_arch_name = loongarch64_gdb_arch_name;
948 }
949
950 #define DEFINE_LOONGARCH_CPU_TYPE(size, model, initfn) \
951 { \
952 .parent = TYPE_LOONGARCH##size##_CPU, \
953 .instance_init = initfn, \
954 .name = LOONGARCH_CPU_TYPE_NAME(model), \
955 }
956
957 static const TypeInfo loongarch_cpu_type_infos[] = {
958 {
959 .name = TYPE_LOONGARCH_CPU,
960 .parent = TYPE_CPU,
961 .instance_size = sizeof(LoongArchCPU),
962 .instance_align = __alignof(LoongArchCPU),
963 .instance_init = loongarch_cpu_init,
964
965 .abstract = true,
966 .class_size = sizeof(LoongArchCPUClass),
967 .class_init = loongarch_cpu_class_init,
968 },
969 {
970 .name = TYPE_LOONGARCH32_CPU,
971 .parent = TYPE_LOONGARCH_CPU,
972
973 .abstract = true,
974 .class_init = loongarch32_cpu_class_init,
975 },
976 {
977 .name = TYPE_LOONGARCH64_CPU,
978 .parent = TYPE_LOONGARCH_CPU,
979
980 .abstract = true,
981 .class_init = loongarch64_cpu_class_init,
982 },
983 DEFINE_LOONGARCH_CPU_TYPE(64, "la464", loongarch_la464_initfn),
984 DEFINE_LOONGARCH_CPU_TYPE(32, "la132", loongarch_la132_initfn),
985 DEFINE_LOONGARCH_CPU_TYPE(64, "max", loongarch_max_initfn),
986 #if defined(CONFIG_KVM)
987 DEFINE_LOONGARCH_CPU_TYPE(64, "host", loongarch_host_initfn),
988 #endif
989 };
990
991 DEFINE_TYPES(loongarch_cpu_type_infos)