1 /* SPDX-License-Identifier: GPL-2.0-or-later */
5 * Copyright (c) 2021 Loongson Technology Corporation Limited
8 #ifndef LOONGARCH_CPU_H
9 #define LOONGARCH_CPU_H
11 #include "qemu/int128.h"
12 #include "exec/cpu-defs.h"
13 #include "fpu/softfloat-types.h"
14 #include "hw/registerfields.h"
15 #include "qemu/timer.h"
16 #ifndef CONFIG_USER_ONLY
17 #include "exec/memory.h"
22 #define IOCSRF_NODECNT 1
24 #define IOCSRF_EXTIOI 3
25 #define IOCSRF_CSRIPI 4
26 #define IOCSRF_FREQCSR 5
27 #define IOCSRF_FREQSCALE 6
28 #define IOCSRF_DVFSV1 7
32 #define VERSION_REG 0x0
33 #define FEATURE_REG 0x8
34 #define VENDOR_REG 0x10
35 #define CPUNAME_REG 0x20
36 #define MISC_FUNC_REG 0x420
37 #define IOCSRM_EXTIOI_EN 48
39 #define IOCSR_MEM_SIZE 0x428
41 #define TCG_GUEST_DEFAULT_MO (0)
43 #define FCSR0_M1 0x1f /* FCSR1 mask, Enables */
44 #define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */
45 #define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */
46 #define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */
48 FIELD(FCSR0
, ENABLES
, 0, 5)
49 FIELD(FCSR0
, RM
, 8, 2)
50 FIELD(FCSR0
, FLAGS
, 16, 5)
51 FIELD(FCSR0
, CAUSE
, 24, 5)
53 #define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE)
54 #define SET_FP_CAUSE(REG, V) \
56 (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \
58 #define UPDATE_FP_CAUSE(REG, V) \
60 (REG) |= FIELD_DP32(0, FCSR0, CAUSE, V); \
63 #define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES)
64 #define SET_FP_ENABLES(REG, V) \
66 (REG) = FIELD_DP32(REG, FCSR0, ENABLES, V); \
69 #define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS)
70 #define SET_FP_FLAGS(REG, V) \
72 (REG) = FIELD_DP32(REG, FCSR0, FLAGS, V); \
75 #define UPDATE_FP_FLAGS(REG, V) \
77 (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \
81 #define FP_UNDERFLOW 2
86 #define EXCODE(code, subcode) ( ((subcode) << 6) | (code) )
87 #define EXCODE_MCODE(code) ( (code) & 0x3f )
88 #define EXCODE_SUBCODE(code) ( (code) >> 6 )
90 #define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */
91 #define EXCCODE_INT EXCODE(0, 0)
92 #define EXCCODE_PIL EXCODE(1, 0)
93 #define EXCCODE_PIS EXCODE(2, 0)
94 #define EXCCODE_PIF EXCODE(3, 0)
95 #define EXCCODE_PME EXCODE(4, 0)
96 #define EXCCODE_PNR EXCODE(5, 0)
97 #define EXCCODE_PNX EXCODE(6, 0)
98 #define EXCCODE_PPI EXCODE(7, 0)
99 #define EXCCODE_ADEF EXCODE(8, 0) /* Different exception subcode */
100 #define EXCCODE_ADEM EXCODE(8, 1)
101 #define EXCCODE_ALE EXCODE(9, 0)
102 #define EXCCODE_BCE EXCODE(10, 0)
103 #define EXCCODE_SYS EXCODE(11, 0)
104 #define EXCCODE_BRK EXCODE(12, 0)
105 #define EXCCODE_INE EXCODE(13, 0)
106 #define EXCCODE_IPE EXCODE(14, 0)
107 #define EXCCODE_FPD EXCODE(15, 0)
108 #define EXCCODE_SXD EXCODE(16, 0)
109 #define EXCCODE_ASXD EXCODE(17, 0)
110 #define EXCCODE_FPE EXCODE(18, 0) /* Different exception subcode */
111 #define EXCCODE_VFPE EXCODE(18, 1)
112 #define EXCCODE_WPEF EXCODE(19, 0) /* Different exception subcode */
113 #define EXCCODE_WPEM EXCODE(19, 1)
114 #define EXCCODE_BTD EXCODE(20, 0)
115 #define EXCCODE_BTE EXCODE(21, 0)
116 #define EXCCODE_DBP EXCODE(26, 0) /* Reserved subcode used for debug */
119 FIELD(CPUCFG0
, PRID
, 0, 32)
122 FIELD(CPUCFG1
, ARCH
, 0, 2)
123 FIELD(CPUCFG1
, PGMMU
, 2, 1)
124 FIELD(CPUCFG1
, IOCSR
, 3, 1)
125 FIELD(CPUCFG1
, PALEN
, 4, 8)
126 FIELD(CPUCFG1
, VALEN
, 12, 8)
127 FIELD(CPUCFG1
, UAL
, 20, 1)
128 FIELD(CPUCFG1
, RI
, 21, 1)
129 FIELD(CPUCFG1
, EP
, 22, 1)
130 FIELD(CPUCFG1
, RPLV
, 23, 1)
131 FIELD(CPUCFG1
, HP
, 24, 1)
132 FIELD(CPUCFG1
, IOCSR_BRD
, 25, 1)
133 FIELD(CPUCFG1
, MSG_INT
, 26, 1)
136 #define CPUCFG1_ARCH_LA32R 0
137 #define CPUCFG1_ARCH_LA32 1
138 #define CPUCFG1_ARCH_LA64 2
141 FIELD(CPUCFG2
, FP
, 0, 1)
142 FIELD(CPUCFG2
, FP_SP
, 1, 1)
143 FIELD(CPUCFG2
, FP_DP
, 2, 1)
144 FIELD(CPUCFG2
, FP_VER
, 3, 3)
145 FIELD(CPUCFG2
, LSX
, 6, 1)
146 FIELD(CPUCFG2
, LASX
, 7, 1)
147 FIELD(CPUCFG2
, COMPLEX
, 8, 1)
148 FIELD(CPUCFG2
, CRYPTO
, 9, 1)
149 FIELD(CPUCFG2
, LVZ
, 10, 1)
150 FIELD(CPUCFG2
, LVZ_VER
, 11, 3)
151 FIELD(CPUCFG2
, LLFTP
, 14, 1)
152 FIELD(CPUCFG2
, LLFTP_VER
, 15, 3)
153 FIELD(CPUCFG2
, LBT_X86
, 18, 1)
154 FIELD(CPUCFG2
, LBT_ARM
, 19, 1)
155 FIELD(CPUCFG2
, LBT_MIPS
, 20, 1)
156 FIELD(CPUCFG2
, LSPW
, 21, 1)
157 FIELD(CPUCFG2
, LAM
, 22, 1)
160 FIELD(CPUCFG3
, CCDMA
, 0, 1)
161 FIELD(CPUCFG3
, SFB
, 1, 1)
162 FIELD(CPUCFG3
, UCACC
, 2, 1)
163 FIELD(CPUCFG3
, LLEXC
, 3, 1)
164 FIELD(CPUCFG3
, SCDLY
, 4, 1)
165 FIELD(CPUCFG3
, LLDBAR
, 5, 1)
166 FIELD(CPUCFG3
, ITLBHMC
, 6, 1)
167 FIELD(CPUCFG3
, ICHMC
, 7, 1)
168 FIELD(CPUCFG3
, SPW_LVL
, 8, 3)
169 FIELD(CPUCFG3
, SPW_HP_HF
, 11, 1)
170 FIELD(CPUCFG3
, RVA
, 12, 1)
171 FIELD(CPUCFG3
, RVAMAX
, 13, 4)
174 FIELD(CPUCFG4
, CC_FREQ
, 0, 32)
177 FIELD(CPUCFG5
, CC_MUL
, 0, 16)
178 FIELD(CPUCFG5
, CC_DIV
, 16, 16)
181 FIELD(CPUCFG6
, PMP
, 0, 1)
182 FIELD(CPUCFG6
, PMVER
, 1, 3)
183 FIELD(CPUCFG6
, PMNUM
, 4, 4)
184 FIELD(CPUCFG6
, PMBITS
, 8, 6)
185 FIELD(CPUCFG6
, UPM
, 14, 1)
187 /* cpucfg[16] bits */
188 FIELD(CPUCFG16
, L1_IUPRE
, 0, 1)
189 FIELD(CPUCFG16
, L1_IUUNIFY
, 1, 1)
190 FIELD(CPUCFG16
, L1_DPRE
, 2, 1)
191 FIELD(CPUCFG16
, L2_IUPRE
, 3, 1)
192 FIELD(CPUCFG16
, L2_IUUNIFY
, 4, 1)
193 FIELD(CPUCFG16
, L2_IUPRIV
, 5, 1)
194 FIELD(CPUCFG16
, L2_IUINCL
, 6, 1)
195 FIELD(CPUCFG16
, L2_DPRE
, 7, 1)
196 FIELD(CPUCFG16
, L2_DPRIV
, 8, 1)
197 FIELD(CPUCFG16
, L2_DINCL
, 9, 1)
198 FIELD(CPUCFG16
, L3_IUPRE
, 10, 1)
199 FIELD(CPUCFG16
, L3_IUUNIFY
, 11, 1)
200 FIELD(CPUCFG16
, L3_IUPRIV
, 12, 1)
201 FIELD(CPUCFG16
, L3_IUINCL
, 13, 1)
202 FIELD(CPUCFG16
, L3_DPRE
, 14, 1)
203 FIELD(CPUCFG16
, L3_DPRIV
, 15, 1)
204 FIELD(CPUCFG16
, L3_DINCL
, 16, 1)
206 /* cpucfg[17] bits */
207 FIELD(CPUCFG17
, L1IU_WAYS
, 0, 16)
208 FIELD(CPUCFG17
, L1IU_SETS
, 16, 8)
209 FIELD(CPUCFG17
, L1IU_SIZE
, 24, 7)
211 /* cpucfg[18] bits */
212 FIELD(CPUCFG18
, L1D_WAYS
, 0, 16)
213 FIELD(CPUCFG18
, L1D_SETS
, 16, 8)
214 FIELD(CPUCFG18
, L1D_SIZE
, 24, 7)
216 /* cpucfg[19] bits */
217 FIELD(CPUCFG19
, L2IU_WAYS
, 0, 16)
218 FIELD(CPUCFG19
, L2IU_SETS
, 16, 8)
219 FIELD(CPUCFG19
, L2IU_SIZE
, 24, 7)
221 /* cpucfg[20] bits */
222 FIELD(CPUCFG20
, L3IU_WAYS
, 0, 16)
223 FIELD(CPUCFG20
, L3IU_SETS
, 16, 8)
224 FIELD(CPUCFG20
, L3IU_SIZE
, 24, 7)
227 FIELD(CSR_CRMD
, PLV
, 0, 2)
228 FIELD(CSR_CRMD
, IE
, 2, 1)
229 FIELD(CSR_CRMD
, DA
, 3, 1)
230 FIELD(CSR_CRMD
, PG
, 4, 1)
231 FIELD(CSR_CRMD
, DATF
, 5, 2)
232 FIELD(CSR_CRMD
, DATM
, 7, 2)
233 FIELD(CSR_CRMD
, WE
, 9, 1)
235 extern const char * const regnames
[32];
236 extern const char * const fregnames
[32];
242 #define LOONGARCH_STLB 2048 /* 2048 STLB */
243 #define LOONGARCH_MTLB 64 /* 64 MTLB */
244 #define LOONGARCH_TLB_MAX (LOONGARCH_STLB + LOONGARCH_MTLB)
247 * define the ASID PS E VPPN field of TLB
249 FIELD(TLB_MISC
, E
, 0, 1)
250 FIELD(TLB_MISC
, ASID
, 1, 10)
251 FIELD(TLB_MISC
, VPPN
, 13, 35)
252 FIELD(TLB_MISC
, PS
, 48, 6)
254 #define LSX_LEN (128)
255 #define LASX_LEN (256)
258 int8_t B
[LASX_LEN
/ 8];
259 int16_t H
[LASX_LEN
/ 16];
260 int32_t W
[LASX_LEN
/ 32];
261 int64_t D
[LASX_LEN
/ 64];
262 uint8_t UB
[LASX_LEN
/ 8];
263 uint16_t UH
[LASX_LEN
/ 16];
264 uint32_t UW
[LASX_LEN
/ 32];
265 uint64_t UD
[LASX_LEN
/ 64];
266 Int128 Q
[LASX_LEN
/ 128];
269 typedef union fpr_t fpr_t
;
274 struct LoongArchTLB
{
276 /* Fields corresponding to CSR_TLBELO0/1 */
280 typedef struct LoongArchTLB LoongArchTLB
;
282 typedef struct CPUArchState
{
287 float_status fp_status
;
295 uint64_t lladdr
; /* LL virtual address compared against SC */
311 uint64_t CSR_TLBELO0
;
312 uint64_t CSR_TLBELO1
;
324 uint64_t CSR_SAVE
[16];
331 uint64_t CSR_IMPCTL1
;
332 uint64_t CSR_IMPCTL2
;
333 uint64_t CSR_TLBRENTRY
;
334 uint64_t CSR_TLBRBADV
;
335 uint64_t CSR_TLBRERA
;
336 uint64_t CSR_TLBRSAVE
;
337 uint64_t CSR_TLBRELO0
;
338 uint64_t CSR_TLBRELO1
;
339 uint64_t CSR_TLBREHI
;
340 uint64_t CSR_TLBRPRMD
;
341 uint64_t CSR_MERRCTL
;
342 uint64_t CSR_MERRINFO1
;
343 uint64_t CSR_MERRINFO2
;
344 uint64_t CSR_MERRENTRY
;
345 uint64_t CSR_MERRERA
;
346 uint64_t CSR_MERRSAVE
;
354 #ifndef CONFIG_USER_ONLY
355 LoongArchTLB tlb
[LOONGARCH_TLB_MAX
];
357 AddressSpace address_space_iocsr
;
358 MemoryRegion system_iocsr
;
359 MemoryRegion iocsr_mem
;
361 uint64_t elf_address
;
362 /* Store ipistate to access from this struct */
363 DeviceState
*ipistate
;
369 * @env: #CPULoongArchState
378 CPUNegativeOffsetState neg
;
379 CPULoongArchState env
;
383 /* 'compatible' string for this CPU for Linux device trees */
384 const char *dtb_compatible
;
387 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
388 #define TYPE_LOONGARCH32_CPU "loongarch32-cpu"
389 #define TYPE_LOONGARCH64_CPU "loongarch64-cpu"
391 OBJECT_DECLARE_CPU_TYPE(LoongArchCPU
, LoongArchCPUClass
,
396 * @parent_realize: The parent class' realize handler.
397 * @parent_phases: The parent class' reset phase handlers.
399 * A LoongArch CPU model.
401 struct LoongArchCPUClass
{
403 CPUClass parent_class
;
406 DeviceRealize parent_realize
;
407 ResettablePhases parent_phases
;
411 * LoongArch CPUs has 4 privilege levels.
412 * 0 for kernel mode, 3 for user mode.
413 * Define an extra index for DA(direct addressing) mode.
415 #define MMU_PLV_KERNEL 0
416 #define MMU_PLV_USER 3
417 #define MMU_IDX_KERNEL MMU_PLV_KERNEL
418 #define MMU_IDX_USER MMU_PLV_USER
421 static inline int cpu_mmu_index(CPULoongArchState
*env
, bool ifetch
)
423 #ifdef CONFIG_USER_ONLY
426 if (FIELD_EX64(env
->CSR_CRMD
, CSR_CRMD
, PG
)) {
427 return FIELD_EX64(env
->CSR_CRMD
, CSR_CRMD
, PLV
);
433 static inline bool is_la64(CPULoongArchState
*env
)
435 return FIELD_EX32(env
->cpucfg
[1], CPUCFG1
, ARCH
) == CPUCFG1_ARCH_LA64
;
438 static inline bool is_va32(CPULoongArchState
*env
)
440 /* VA32 if !LA64 or VA32L[1-3] */
441 bool va32
= !is_la64(env
);
442 uint64_t plv
= FIELD_EX64(env
->CSR_CRMD
, CSR_CRMD
, PLV
);
443 if (plv
>= 1 && (FIELD_EX64(env
->CSR_MISC
, CSR_MISC
, VA32
) & (1 << plv
))) {
449 static inline void set_pc(CPULoongArchState
*env
, uint64_t value
)
452 env
->pc
= (uint32_t)value
;
459 * LoongArch CPUs hardware flags.
461 #define HW_FLAGS_PLV_MASK R_CSR_CRMD_PLV_MASK /* 0x03 */
462 #define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */
463 #define HW_FLAGS_EUEN_FPE 0x04
464 #define HW_FLAGS_EUEN_SXE 0x08
465 #define HW_FLAGS_EUEN_ASXE 0x10
466 #define HW_FLAGS_VA32 0x20
468 static inline void cpu_get_tb_cpu_state(CPULoongArchState
*env
, vaddr
*pc
,
469 uint64_t *cs_base
, uint32_t *flags
)
473 *flags
= env
->CSR_CRMD
& (R_CSR_CRMD_PLV_MASK
| R_CSR_CRMD_PG_MASK
);
474 *flags
|= FIELD_EX64(env
->CSR_EUEN
, CSR_EUEN
, FPE
) * HW_FLAGS_EUEN_FPE
;
475 *flags
|= FIELD_EX64(env
->CSR_EUEN
, CSR_EUEN
, SXE
) * HW_FLAGS_EUEN_SXE
;
476 *flags
|= FIELD_EX64(env
->CSR_EUEN
, CSR_EUEN
, ASXE
) * HW_FLAGS_EUEN_ASXE
;
477 *flags
|= is_va32(env
) * HW_FLAGS_VA32
;
480 void loongarch_cpu_list(void);
482 #define cpu_list loongarch_cpu_list
484 #include "exec/cpu-all.h"
486 #define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU
487 #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
488 #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
490 #endif /* LOONGARCH_CPU_H */