1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * LoongArch emulation helpers for CSRs 4 * 5 * Copyright (c) 2021 Loongson Technology Corporation Limited 6 */ 7 8 #include "qemu/osdep.h" 9 #include "qemu/log.h" 10 #include "qemu/main-loop.h" 11 #include "cpu.h" 12 #include "internals.h" 13 #include "qemu/host-utils.h" 14 #include "exec/helper-proto.h" 15 #include "exec/exec-all.h" 16 #include "exec/cpu_ldst.h" 17 #include "hw/irq.h" 18 #include "cpu-csr.h" 19 20 target_ulong helper_csrrd_pgd(CPULoongArchState *env) 21 { 22 int64_t v; 23 24 if (env->CSR_TLBRERA & 0x1) { 25 v = env->CSR_TLBRBADV; 26 } else { 27 v = env->CSR_BADV; 28 } 29 30 if ((v >> 63) & 0x1) { 31 v = env->CSR_PGDH; 32 } else { 33 v = env->CSR_PGDL; 34 } 35 36 return v; 37 } 38 39 target_ulong helper_csrrd_cpuid(CPULoongArchState *env) 40 { 41 LoongArchCPU *lac = env_archcpu(env); 42 43 env->CSR_CPUID = CPU(lac)->cpu_index; 44 45 return env->CSR_CPUID; 46 } 47 48 target_ulong helper_csrrd_tval(CPULoongArchState *env) 49 { 50 LoongArchCPU *cpu = env_archcpu(env); 51 52 return cpu_loongarch_get_constant_timer_ticks(cpu); 53 } 54 55 target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val) 56 { 57 int64_t old_v = env->CSR_ESTAT; 58 59 /* Only IS[1:0] can be written */ 60 env->CSR_ESTAT = deposit64(env->CSR_ESTAT, 0, 2, val); 61 62 return old_v; 63 } 64 65 target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val) 66 { 67 int64_t old_v = env->CSR_ASID; 68 69 /* Only ASID filed of CSR_ASID can be written */ 70 env->CSR_ASID = deposit64(env->CSR_ASID, 0, 10, val); 71 if (old_v != env->CSR_ASID) { 72 tlb_flush(env_cpu(env)); 73 } 74 return old_v; 75 } 76 77 target_ulong helper_csrwr_tcfg(CPULoongArchState *env, target_ulong val) 78 { 79 LoongArchCPU *cpu = env_archcpu(env); 80 int64_t old_v = env->CSR_TCFG; 81 82 cpu_loongarch_store_constant_timer_config(cpu, val); 83 84 return old_v; 85 } 86 87 target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val) 88 { 89 LoongArchCPU *cpu = env_archcpu(env); 90 int64_t old_v = 0; 91 92 if (val & 0x1) { 93 bql_lock(); 94 loongarch_cpu_set_irq(cpu, IRQ_TIMER, 0); 95 bql_unlock(); 96 } 97 return old_v; 98 } 99 100 target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) 101 { 102 int shift; 103 int64_t old_v = env->CSR_PWCL; 104 105 /* 106 * The real hardware only supports 64bit PTE width now, 128bit or others 107 * treated as illegal. 108 */ 109 shift = FIELD_EX64(val, CSR_PWCL, PTEWIDTH); 110 if (shift) { 111 qemu_log_mask(LOG_GUEST_ERROR, 112 "Attempted set pte width with %d bit\n", 64 << shift); 113 val = FIELD_DP64(val, CSR_PWCL, PTEWIDTH, 0); 114 } 115 116 env->CSR_PWCL = val; 117 return old_v; 118 } 119