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 "sysemu/tcg.h" 15 #include "sysemu/kvm.h" 16 #include "kvm/kvm_loongarch.h" 17 #include "exec/exec-all.h" 18 #include "cpu.h" 19 #include "internals.h" 20 #include "fpu/softfloat-helpers.h" 21 #include "cpu-csr.h" 22 #ifndef CONFIG_USER_ONLY 23 #include "sysemu/reset.h" 24 #endif 25 #include "vec.h" 26 #ifdef CONFIG_KVM 27 #include <linux/kvm.h> 28 #endif 29 #ifdef CONFIG_TCG 30 #include "exec/cpu_ldst.h" 31 #include "tcg/tcg.h" 32 #endif 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 const char * const excp_names[] = { 49 [EXCCODE_INT] = "Interrupt", 50 [EXCCODE_PIL] = "Page invalid exception for load", 51 [EXCCODE_PIS] = "Page invalid exception for store", 52 [EXCCODE_PIF] = "Page invalid exception for fetch", 53 [EXCCODE_PME] = "Page modified exception", 54 [EXCCODE_PNR] = "Page Not Readable exception", 55 [EXCCODE_PNX] = "Page Not Executable exception", 56 [EXCCODE_PPI] = "Page Privilege error", 57 [EXCCODE_ADEF] = "Address error for instruction fetch", 58 [EXCCODE_ADEM] = "Address error for Memory access", 59 [EXCCODE_SYS] = "Syscall", 60 [EXCCODE_BRK] = "Break", 61 [EXCCODE_INE] = "Instruction Non-Existent", 62 [EXCCODE_IPE] = "Instruction privilege error", 63 [EXCCODE_FPD] = "Floating Point Disabled", 64 [EXCCODE_FPE] = "Floating Point Exception", 65 [EXCCODE_DBP] = "Debug breakpoint", 66 [EXCCODE_BCE] = "Bound Check Exception", 67 [EXCCODE_SXD] = "128 bit vector instructions Disable exception", 68 [EXCCODE_ASXD] = "256 bit vector instructions Disable exception", 69 }; 70 71 const char *loongarch_exception_name(int32_t exception) 72 { 73 assert(excp_names[exception]); 74 return excp_names[exception]; 75 } 76 77 void G_NORETURN do_raise_exception(CPULoongArchState *env, 78 uint32_t exception, 79 uintptr_t pc) 80 { 81 CPUState *cs = env_cpu(env); 82 83 qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n", 84 __func__, 85 exception, 86 loongarch_exception_name(exception)); 87 cs->exception_index = exception; 88 89 cpu_loop_exit_restore(cs, pc); 90 } 91 92 static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) 93 { 94 set_pc(cpu_env(cs), value); 95 } 96 97 static vaddr loongarch_cpu_get_pc(CPUState *cs) 98 { 99 return cpu_env(cs)->pc; 100 } 101 102 #ifndef CONFIG_USER_ONLY 103 #include "hw/loongarch/virt.h" 104 105 void loongarch_cpu_set_irq(void *opaque, int irq, int level) 106 { 107 LoongArchCPU *cpu = opaque; 108 CPULoongArchState *env = &cpu->env; 109 CPUState *cs = CPU(cpu); 110 111 if (irq < 0 || irq >= N_IRQS) { 112 return; 113 } 114 115 if (kvm_enabled()) { 116 kvm_loongarch_set_interrupt(cpu, irq, level); 117 } else if (tcg_enabled()) { 118 env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0); 119 if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) { 120 cpu_interrupt(cs, CPU_INTERRUPT_HARD); 121 } else { 122 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); 123 } 124 } 125 } 126 127 static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env) 128 { 129 bool ret = 0; 130 131 ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) && 132 !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST))); 133 134 return ret; 135 } 136 137 /* Check if there is pending and not masked out interrupt */ 138 static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env) 139 { 140 uint32_t pending; 141 uint32_t status; 142 143 pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); 144 status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); 145 146 return (pending & status) != 0; 147 } 148 #endif 149 150 #ifdef CONFIG_TCG 151 #ifndef CONFIG_USER_ONLY 152 static void loongarch_cpu_do_interrupt(CPUState *cs) 153 { 154 CPULoongArchState *env = cpu_env(cs); 155 bool update_badinstr = 1; 156 int cause = -1; 157 const char *name; 158 bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR); 159 uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS); 160 161 if (cs->exception_index != EXCCODE_INT) { 162 if (cs->exception_index < 0 || 163 cs->exception_index >= ARRAY_SIZE(excp_names)) { 164 name = "unknown"; 165 } else { 166 name = excp_names[cs->exception_index]; 167 } 168 169 qemu_log_mask(CPU_LOG_INT, 170 "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx 171 " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__, 172 env->pc, env->CSR_ERA, env->CSR_TLBRERA, name); 173 } 174 175 switch (cs->exception_index) { 176 case EXCCODE_DBP: 177 env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1); 178 env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC); 179 goto set_DERA; 180 set_DERA: 181 env->CSR_DERA = env->pc; 182 env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1); 183 set_pc(env, env->CSR_EENTRY + 0x480); 184 break; 185 case EXCCODE_INT: 186 if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) { 187 env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1); 188 goto set_DERA; 189 } 190 QEMU_FALLTHROUGH; 191 case EXCCODE_PIF: 192 case EXCCODE_ADEF: 193 cause = cs->exception_index; 194 update_badinstr = 0; 195 break; 196 case EXCCODE_SYS: 197 case EXCCODE_BRK: 198 case EXCCODE_INE: 199 case EXCCODE_IPE: 200 case EXCCODE_FPD: 201 case EXCCODE_FPE: 202 case EXCCODE_SXD: 203 case EXCCODE_ASXD: 204 env->CSR_BADV = env->pc; 205 QEMU_FALLTHROUGH; 206 case EXCCODE_BCE: 207 case EXCCODE_ADEM: 208 case EXCCODE_PIL: 209 case EXCCODE_PIS: 210 case EXCCODE_PME: 211 case EXCCODE_PNR: 212 case EXCCODE_PNX: 213 case EXCCODE_PPI: 214 cause = cs->exception_index; 215 break; 216 default: 217 qemu_log("Error: exception(%d) has not been supported\n", 218 cs->exception_index); 219 abort(); 220 } 221 222 if (update_badinstr) { 223 env->CSR_BADI = cpu_ldl_code(env, env->pc); 224 } 225 226 /* Save PLV and IE */ 227 if (tlbfill) { 228 env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV, 229 FIELD_EX64(env->CSR_CRMD, 230 CSR_CRMD, PLV)); 231 env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE, 232 FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); 233 /* set the DA mode */ 234 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1); 235 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0); 236 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, 237 PC, (env->pc >> 2)); 238 } else { 239 env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, 240 EXCODE_MCODE(cause)); 241 env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ESUBCODE, 242 EXCODE_SUBCODE(cause)); 243 env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV, 244 FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV)); 245 env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE, 246 FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE)); 247 env->CSR_ERA = env->pc; 248 } 249 250 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0); 251 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0); 252 253 if (vec_size) { 254 vec_size = (1 << vec_size) * 4; 255 } 256 257 if (cs->exception_index == EXCCODE_INT) { 258 /* Interrupt */ 259 uint32_t vector = 0; 260 uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS); 261 pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE); 262 263 /* Find the highest-priority interrupt. */ 264 vector = 31 - clz32(pending); 265 set_pc(env, env->CSR_EENTRY + \ 266 (EXCCODE_EXTERNAL_INT + vector) * vec_size); 267 qemu_log_mask(CPU_LOG_INT, 268 "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx 269 " cause %d\n" " A " TARGET_FMT_lx " D " 270 TARGET_FMT_lx " vector = %d ExC " TARGET_FMT_lx "ExS" 271 TARGET_FMT_lx "\n", 272 __func__, env->pc, env->CSR_ERA, 273 cause, env->CSR_BADV, env->CSR_DERA, vector, 274 env->CSR_ECFG, env->CSR_ESTAT); 275 } else { 276 if (tlbfill) { 277 set_pc(env, env->CSR_TLBRENTRY); 278 } else { 279 set_pc(env, env->CSR_EENTRY + EXCODE_MCODE(cause) * vec_size); 280 } 281 qemu_log_mask(CPU_LOG_INT, 282 "%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx 283 " cause %d%s\n, ESTAT " TARGET_FMT_lx 284 " EXCFG " TARGET_FMT_lx " BADVA " TARGET_FMT_lx 285 "BADI " TARGET_FMT_lx " SYS_NUM " TARGET_FMT_lu 286 " cpu %d asid " TARGET_FMT_lx "\n", __func__, env->pc, 287 tlbfill ? env->CSR_TLBRERA : env->CSR_ERA, 288 cause, tlbfill ? "(refill)" : "", env->CSR_ESTAT, 289 env->CSR_ECFG, 290 tlbfill ? env->CSR_TLBRBADV : env->CSR_BADV, 291 env->CSR_BADI, env->gpr[11], cs->cpu_index, 292 env->CSR_ASID); 293 } 294 cs->exception_index = -1; 295 } 296 297 static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, 298 vaddr addr, unsigned size, 299 MMUAccessType access_type, 300 int mmu_idx, MemTxAttrs attrs, 301 MemTxResult response, 302 uintptr_t retaddr) 303 { 304 CPULoongArchState *env = cpu_env(cs); 305 306 if (access_type == MMU_INST_FETCH) { 307 do_raise_exception(env, EXCCODE_ADEF, retaddr); 308 } else { 309 do_raise_exception(env, EXCCODE_ADEM, retaddr); 310 } 311 } 312 313 static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 314 { 315 if (interrupt_request & CPU_INTERRUPT_HARD) { 316 CPULoongArchState *env = cpu_env(cs); 317 318 if (cpu_loongarch_hw_interrupts_enabled(env) && 319 cpu_loongarch_hw_interrupts_pending(env)) { 320 /* Raise it */ 321 cs->exception_index = EXCCODE_INT; 322 loongarch_cpu_do_interrupt(cs); 323 return true; 324 } 325 } 326 return false; 327 } 328 #endif 329 330 static void loongarch_cpu_synchronize_from_tb(CPUState *cs, 331 const TranslationBlock *tb) 332 { 333 tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL)); 334 set_pc(cpu_env(cs), tb->pc); 335 } 336 337 static void loongarch_restore_state_to_opc(CPUState *cs, 338 const TranslationBlock *tb, 339 const uint64_t *data) 340 { 341 set_pc(cpu_env(cs), data[0]); 342 } 343 #endif /* CONFIG_TCG */ 344 345 static bool loongarch_cpu_has_work(CPUState *cs) 346 { 347 #ifdef CONFIG_USER_ONLY 348 return true; 349 #else 350 bool has_work = false; 351 352 if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && 353 cpu_loongarch_hw_interrupts_pending(cpu_env(cs))) { 354 has_work = true; 355 } 356 357 return has_work; 358 #endif 359 } 360 361 static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) 362 { 363 CPULoongArchState *env = cpu_env(cs); 364 365 if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { 366 return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); 367 } 368 return MMU_DA_IDX; 369 } 370 371 static void loongarch_la464_initfn(Object *obj) 372 { 373 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 374 CPULoongArchState *env = &cpu->env; 375 int i; 376 377 for (i = 0; i < 21; i++) { 378 env->cpucfg[i] = 0x0; 379 } 380 381 cpu->dtb_compatible = "loongarch,Loongson-3A5000"; 382 env->cpucfg[0] = 0x14c010; /* PRID */ 383 384 uint32_t data = 0; 385 data = FIELD_DP32(data, CPUCFG1, ARCH, 2); 386 data = FIELD_DP32(data, CPUCFG1, PGMMU, 1); 387 data = FIELD_DP32(data, CPUCFG1, IOCSR, 1); 388 data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); 389 data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); 390 data = FIELD_DP32(data, CPUCFG1, UAL, 1); 391 data = FIELD_DP32(data, CPUCFG1, RI, 1); 392 data = FIELD_DP32(data, CPUCFG1, EP, 1); 393 data = FIELD_DP32(data, CPUCFG1, RPLV, 1); 394 data = FIELD_DP32(data, CPUCFG1, HP, 1); 395 data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1); 396 env->cpucfg[1] = data; 397 398 data = 0; 399 data = FIELD_DP32(data, CPUCFG2, FP, 1); 400 data = FIELD_DP32(data, CPUCFG2, FP_SP, 1); 401 data = FIELD_DP32(data, CPUCFG2, FP_DP, 1); 402 data = FIELD_DP32(data, CPUCFG2, FP_VER, 1); 403 data = FIELD_DP32(data, CPUCFG2, LSX, 1), 404 data = FIELD_DP32(data, CPUCFG2, LASX, 1), 405 data = FIELD_DP32(data, CPUCFG2, LLFTP, 1); 406 data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1); 407 data = FIELD_DP32(data, CPUCFG2, LSPW, 1); 408 data = FIELD_DP32(data, CPUCFG2, LAM, 1); 409 env->cpucfg[2] = data; 410 411 env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */ 412 413 data = 0; 414 data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1); 415 data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1); 416 env->cpucfg[5] = data; 417 418 data = 0; 419 data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1); 420 data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1); 421 data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1); 422 data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1); 423 data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1); 424 data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1); 425 data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1); 426 data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1); 427 env->cpucfg[16] = data; 428 429 data = 0; 430 data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 3); 431 data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 8); 432 data = FIELD_DP32(data, CPUCFG17, L1IU_SIZE, 6); 433 env->cpucfg[17] = data; 434 435 data = 0; 436 data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 3); 437 data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 8); 438 data = FIELD_DP32(data, CPUCFG18, L1D_SIZE, 6); 439 env->cpucfg[18] = data; 440 441 data = 0; 442 data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 15); 443 data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 8); 444 data = FIELD_DP32(data, CPUCFG19, L2IU_SIZE, 6); 445 env->cpucfg[19] = data; 446 447 data = 0; 448 data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 15); 449 data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 14); 450 data = FIELD_DP32(data, CPUCFG20, L3IU_SIZE, 6); 451 env->cpucfg[20] = data; 452 453 env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa); 454 loongarch_cpu_post_init(obj); 455 } 456 457 static void loongarch_la132_initfn(Object *obj) 458 { 459 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 460 CPULoongArchState *env = &cpu->env; 461 462 int i; 463 464 for (i = 0; i < 21; i++) { 465 env->cpucfg[i] = 0x0; 466 } 467 468 cpu->dtb_compatible = "loongarch,Loongson-1C103"; 469 env->cpucfg[0] = 0x148042; /* PRID */ 470 471 uint32_t data = 0; 472 data = FIELD_DP32(data, CPUCFG1, ARCH, 1); /* LA32 */ 473 data = FIELD_DP32(data, CPUCFG1, PGMMU, 1); 474 data = FIELD_DP32(data, CPUCFG1, IOCSR, 1); 475 data = FIELD_DP32(data, CPUCFG1, PALEN, 0x1f); /* 32 bits */ 476 data = FIELD_DP32(data, CPUCFG1, VALEN, 0x1f); /* 32 bits */ 477 data = FIELD_DP32(data, CPUCFG1, UAL, 1); 478 data = FIELD_DP32(data, CPUCFG1, RI, 0); 479 data = FIELD_DP32(data, CPUCFG1, EP, 0); 480 data = FIELD_DP32(data, CPUCFG1, RPLV, 0); 481 data = FIELD_DP32(data, CPUCFG1, HP, 1); 482 data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1); 483 env->cpucfg[1] = data; 484 } 485 486 static void loongarch_max_initfn(Object *obj) 487 { 488 /* '-cpu max' for TCG: we use cpu la464. */ 489 loongarch_la464_initfn(obj); 490 } 491 492 static void loongarch_cpu_reset_hold(Object *obj) 493 { 494 CPUState *cs = CPU(obj); 495 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj); 496 CPULoongArchState *env = cpu_env(cs); 497 498 if (lacc->parent_phases.hold) { 499 lacc->parent_phases.hold(obj); 500 } 501 502 env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3; 503 env->fcsr0 = 0x0; 504 505 int n; 506 /* Set csr registers value after reset */ 507 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0); 508 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0); 509 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1); 510 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0); 511 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATF, 1); 512 env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DATM, 1); 513 514 env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, FPE, 0); 515 env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, SXE, 0); 516 env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, ASXE, 0); 517 env->CSR_EUEN = FIELD_DP64(env->CSR_EUEN, CSR_EUEN, BTE, 0); 518 519 env->CSR_MISC = 0; 520 521 env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, VS, 0); 522 env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, LIE, 0); 523 524 env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2)); 525 env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0); 526 env->CSR_CPUID = cs->cpu_index; 527 env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0); 528 env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0); 529 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0); 530 env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0); 531 env->CSR_TID = cs->cpu_index; 532 533 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2); 534 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63); 535 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); 536 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); 537 538 for (n = 0; n < 4; n++) { 539 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV0, 0); 540 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV1, 0); 541 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV2, 0); 542 env->CSR_DMW[n] = FIELD_DP64(env->CSR_DMW[n], CSR_DMW, PLV3, 0); 543 } 544 545 #ifndef CONFIG_USER_ONLY 546 env->pc = 0x1c000000; 547 memset(env->tlb, 0, sizeof(env->tlb)); 548 if (kvm_enabled()) { 549 kvm_arch_reset_vcpu(env); 550 } 551 #endif 552 553 #ifdef CONFIG_TCG 554 restore_fp_status(env); 555 #endif 556 cs->exception_index = -1; 557 } 558 559 static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) 560 { 561 info->print_insn = print_insn_loongarch; 562 } 563 564 static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) 565 { 566 CPUState *cs = CPU(dev); 567 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev); 568 Error *local_err = NULL; 569 570 cpu_exec_realizefn(cs, &local_err); 571 if (local_err != NULL) { 572 error_propagate(errp, local_err); 573 return; 574 } 575 576 loongarch_cpu_register_gdb_regs_for_features(cs); 577 578 cpu_reset(cs); 579 qemu_init_vcpu(cs); 580 581 lacc->parent_realize(dev, errp); 582 } 583 584 static bool loongarch_get_lsx(Object *obj, Error **errp) 585 { 586 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 587 bool ret; 588 589 if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { 590 ret = true; 591 } else { 592 ret = false; 593 } 594 return ret; 595 } 596 597 static void loongarch_set_lsx(Object *obj, bool value, Error **errp) 598 { 599 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 600 601 if (value) { 602 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1); 603 } else { 604 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 0); 605 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0); 606 } 607 } 608 609 static bool loongarch_get_lasx(Object *obj, Error **errp) 610 { 611 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 612 bool ret; 613 614 if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) { 615 ret = true; 616 } else { 617 ret = false; 618 } 619 return ret; 620 } 621 622 static void loongarch_set_lasx(Object *obj, bool value, Error **errp) 623 { 624 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 625 626 if (value) { 627 if (!FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { 628 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LSX, 1); 629 } 630 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 1); 631 } else { 632 cpu->env.cpucfg[2] = FIELD_DP32(cpu->env.cpucfg[2], CPUCFG2, LASX, 0); 633 } 634 } 635 636 void loongarch_cpu_post_init(Object *obj) 637 { 638 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 639 640 if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { 641 object_property_add_bool(obj, "lsx", loongarch_get_lsx, 642 loongarch_set_lsx); 643 } 644 if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) { 645 object_property_add_bool(obj, "lasx", loongarch_get_lasx, 646 loongarch_set_lasx); 647 } 648 } 649 650 static void loongarch_cpu_init(Object *obj) 651 { 652 #ifndef CONFIG_USER_ONLY 653 LoongArchCPU *cpu = LOONGARCH_CPU(obj); 654 655 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS); 656 #ifdef CONFIG_TCG 657 timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL, 658 &loongarch_constant_timer_cb, cpu); 659 #endif 660 #endif 661 } 662 663 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) 664 { 665 ObjectClass *oc; 666 667 oc = object_class_by_name(cpu_model); 668 if (!oc) { 669 g_autofree char *typename 670 = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model); 671 oc = object_class_by_name(typename); 672 } 673 674 return oc; 675 } 676 677 void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) 678 { 679 CPULoongArchState *env = cpu_env(cs); 680 int i; 681 682 qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc); 683 qemu_fprintf(f, " FCSR0 0x%08x fp_status 0x%02x\n", env->fcsr0, 684 get_float_exception_flags(&env->fp_status)); 685 686 /* gpr */ 687 for (i = 0; i < 32; i++) { 688 if ((i & 3) == 0) { 689 qemu_fprintf(f, " GPR%02d:", i); 690 } 691 qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]); 692 if ((i & 3) == 3) { 693 qemu_fprintf(f, "\n"); 694 } 695 } 696 697 qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD); 698 qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD); 699 qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN); 700 qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT); 701 qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA); 702 qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV); 703 qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI); 704 qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY); 705 qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 "," 706 " PRCFG3=%016" PRIx64 "\n", 707 env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3); 708 qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY); 709 qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV); 710 qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA); 711 qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG); 712 qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL); 713 714 /* fpr */ 715 if (flags & CPU_DUMP_FPU) { 716 for (i = 0; i < 32; i++) { 717 qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i].vreg.D(0)); 718 if ((i & 3) == 3) { 719 qemu_fprintf(f, "\n"); 720 } 721 } 722 } 723 } 724 725 #ifdef CONFIG_TCG 726 #include "hw/core/tcg-cpu-ops.h" 727 728 static const TCGCPUOps loongarch_tcg_ops = { 729 .initialize = loongarch_translate_init, 730 .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, 731 .restore_state_to_opc = loongarch_restore_state_to_opc, 732 733 #ifndef CONFIG_USER_ONLY 734 .tlb_fill = loongarch_cpu_tlb_fill, 735 .cpu_exec_interrupt = loongarch_cpu_exec_interrupt, 736 .do_interrupt = loongarch_cpu_do_interrupt, 737 .do_transaction_failed = loongarch_cpu_do_transaction_failed, 738 #endif 739 }; 740 #endif /* CONFIG_TCG */ 741 742 #ifndef CONFIG_USER_ONLY 743 #include "hw/core/sysemu-cpu-ops.h" 744 745 static const struct SysemuCPUOps loongarch_sysemu_ops = { 746 .get_phys_page_debug = loongarch_cpu_get_phys_page_debug, 747 }; 748 749 static int64_t loongarch_cpu_get_arch_id(CPUState *cs) 750 { 751 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 752 753 return cpu->phy_id; 754 } 755 #endif 756 757 static void loongarch_cpu_class_init(ObjectClass *c, void *data) 758 { 759 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c); 760 CPUClass *cc = CPU_CLASS(c); 761 DeviceClass *dc = DEVICE_CLASS(c); 762 ResettableClass *rc = RESETTABLE_CLASS(c); 763 764 device_class_set_parent_realize(dc, loongarch_cpu_realizefn, 765 &lacc->parent_realize); 766 resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL, 767 &lacc->parent_phases); 768 769 cc->class_by_name = loongarch_cpu_class_by_name; 770 cc->has_work = loongarch_cpu_has_work; 771 cc->mmu_index = loongarch_cpu_mmu_index; 772 cc->dump_state = loongarch_cpu_dump_state; 773 cc->set_pc = loongarch_cpu_set_pc; 774 cc->get_pc = loongarch_cpu_get_pc; 775 #ifndef CONFIG_USER_ONLY 776 cc->get_arch_id = loongarch_cpu_get_arch_id; 777 dc->vmsd = &vmstate_loongarch_cpu; 778 cc->sysemu_ops = &loongarch_sysemu_ops; 779 #endif 780 cc->disas_set_info = loongarch_cpu_disas_set_info; 781 cc->gdb_read_register = loongarch_cpu_gdb_read_register; 782 cc->gdb_write_register = loongarch_cpu_gdb_write_register; 783 cc->gdb_stop_before_watchpoint = true; 784 785 #ifdef CONFIG_TCG 786 cc->tcg_ops = &loongarch_tcg_ops; 787 #endif 788 } 789 790 static const gchar *loongarch32_gdb_arch_name(CPUState *cs) 791 { 792 return "loongarch32"; 793 } 794 795 static void loongarch32_cpu_class_init(ObjectClass *c, void *data) 796 { 797 CPUClass *cc = CPU_CLASS(c); 798 799 cc->gdb_core_xml_file = "loongarch-base32.xml"; 800 cc->gdb_arch_name = loongarch32_gdb_arch_name; 801 } 802 803 static const gchar *loongarch64_gdb_arch_name(CPUState *cs) 804 { 805 return "loongarch64"; 806 } 807 808 static void loongarch64_cpu_class_init(ObjectClass *c, void *data) 809 { 810 CPUClass *cc = CPU_CLASS(c); 811 812 cc->gdb_core_xml_file = "loongarch-base64.xml"; 813 cc->gdb_arch_name = loongarch64_gdb_arch_name; 814 } 815 816 #define DEFINE_LOONGARCH_CPU_TYPE(size, model, initfn) \ 817 { \ 818 .parent = TYPE_LOONGARCH##size##_CPU, \ 819 .instance_init = initfn, \ 820 .name = LOONGARCH_CPU_TYPE_NAME(model), \ 821 } 822 823 static const TypeInfo loongarch_cpu_type_infos[] = { 824 { 825 .name = TYPE_LOONGARCH_CPU, 826 .parent = TYPE_CPU, 827 .instance_size = sizeof(LoongArchCPU), 828 .instance_align = __alignof(LoongArchCPU), 829 .instance_init = loongarch_cpu_init, 830 831 .abstract = true, 832 .class_size = sizeof(LoongArchCPUClass), 833 .class_init = loongarch_cpu_class_init, 834 }, 835 { 836 .name = TYPE_LOONGARCH32_CPU, 837 .parent = TYPE_LOONGARCH_CPU, 838 839 .abstract = true, 840 .class_init = loongarch32_cpu_class_init, 841 }, 842 { 843 .name = TYPE_LOONGARCH64_CPU, 844 .parent = TYPE_LOONGARCH_CPU, 845 846 .abstract = true, 847 .class_init = loongarch64_cpu_class_init, 848 }, 849 DEFINE_LOONGARCH_CPU_TYPE(64, "la464", loongarch_la464_initfn), 850 DEFINE_LOONGARCH_CPU_TYPE(32, "la132", loongarch_la132_initfn), 851 DEFINE_LOONGARCH_CPU_TYPE(64, "max", loongarch_max_initfn), 852 }; 853 854 DEFINE_TYPES(loongarch_cpu_type_infos) 855