]>
Commit | Line | Data |
---|---|---|
228021f0 SG |
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 | #ifndef LOONGARCH_CPU_H | |
9 | #define LOONGARCH_CPU_H | |
10 | ||
11 | #include "exec/cpu-defs.h" | |
12 | #include "fpu/softfloat-types.h" | |
13 | #include "hw/registerfields.h" | |
dd615fa4 | 14 | #include "qemu/timer.h" |
f84a2aac XY |
15 | #include "exec/memory.h" |
16 | #include "hw/sysbus.h" | |
17 | ||
18 | #define IOCSRF_TEMP 0 | |
19 | #define IOCSRF_NODECNT 1 | |
20 | #define IOCSRF_MSI 2 | |
21 | #define IOCSRF_EXTIOI 3 | |
22 | #define IOCSRF_CSRIPI 4 | |
23 | #define IOCSRF_FREQCSR 5 | |
24 | #define IOCSRF_FREQSCALE 6 | |
25 | #define IOCSRF_DVFSV1 7 | |
26 | #define IOCSRF_GMOD 9 | |
27 | #define IOCSRF_VM 11 | |
28 | ||
29 | #define FEATURE_REG 0x8 | |
30 | #define VENDOR_REG 0x10 | |
31 | #define CPUNAME_REG 0x20 | |
32 | #define MISC_FUNC_REG 0x420 | |
33 | #define IOCSRM_EXTIOI_EN 48 | |
34 | ||
35 | #define IOCSR_MEM_SIZE 0x428 | |
228021f0 SG |
36 | |
37 | #define TCG_GUEST_DEFAULT_MO (0) | |
38 | ||
39 | #define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ | |
40 | #define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ | |
41 | #define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ | |
42 | #define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ | |
43 | ||
44 | FIELD(FCSR0, ENABLES, 0, 5) | |
45 | FIELD(FCSR0, RM, 8, 2) | |
46 | FIELD(FCSR0, FLAGS, 16, 5) | |
47 | FIELD(FCSR0, CAUSE, 24, 5) | |
48 | ||
49 | #define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE) | |
00952d93 QH |
50 | #define SET_FP_CAUSE(REG, V) \ |
51 | do { \ | |
52 | (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \ | |
53 | } while (0) | |
54 | ||
228021f0 | 55 | #define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES) |
00952d93 QH |
56 | #define SET_FP_ENABLES(REG, V) \ |
57 | do { \ | |
58 | (REG) = FIELD_DP32(REG, FCSR0, ENABLES, V); \ | |
59 | } while (0) | |
60 | ||
228021f0 | 61 | #define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS) |
00952d93 QH |
62 | #define SET_FP_FLAGS(REG, V) \ |
63 | do { \ | |
64 | (REG) = FIELD_DP32(REG, FCSR0, FLAGS, V); \ | |
65 | } while (0) | |
66 | ||
228021f0 SG |
67 | #define UPDATE_FP_FLAGS(REG, V) \ |
68 | do { \ | |
69 | (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \ | |
70 | } while (0) | |
71 | ||
72 | #define FP_INEXACT 1 | |
73 | #define FP_UNDERFLOW 2 | |
74 | #define FP_OVERFLOW 4 | |
75 | #define FP_DIV0 8 | |
76 | #define FP_INVALID 16 | |
77 | ||
78 | #define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */ | |
79 | #define EXCCODE_INT 0 | |
80 | #define EXCCODE_PIL 1 | |
81 | #define EXCCODE_PIS 2 | |
82 | #define EXCCODE_PIF 3 | |
83 | #define EXCCODE_PME 4 | |
84 | #define EXCCODE_PNR 5 | |
85 | #define EXCCODE_PNX 6 | |
86 | #define EXCCODE_PPI 7 | |
87 | #define EXCCODE_ADEF 8 /* Different exception subcode */ | |
88 | #define EXCCODE_ADEM 8 | |
89 | #define EXCCODE_ALE 9 | |
90 | #define EXCCODE_BCE 10 | |
91 | #define EXCCODE_SYS 11 | |
92 | #define EXCCODE_BRK 12 | |
93 | #define EXCCODE_INE 13 | |
94 | #define EXCCODE_IPE 14 | |
95 | #define EXCCODE_FPD 15 | |
96 | #define EXCCODE_SXD 16 | |
97 | #define EXCCODE_ASXD 17 | |
98 | #define EXCCODE_FPE 18 /* Different exception subcode */ | |
99 | #define EXCCODE_VFPE 18 | |
100 | #define EXCCODE_WPEF 19 /* Different exception subcode */ | |
101 | #define EXCCODE_WPEM 19 | |
102 | #define EXCCODE_BTD 20 | |
103 | #define EXCCODE_BTE 21 | |
104 | #define EXCCODE_DBP 26 /* Reserved subcode used for debug */ | |
105 | ||
106 | /* cpucfg[0] bits */ | |
107 | FIELD(CPUCFG0, PRID, 0, 32) | |
108 | ||
109 | /* cpucfg[1] bits */ | |
110 | FIELD(CPUCFG1, ARCH, 0, 2) | |
111 | FIELD(CPUCFG1, PGMMU, 2, 1) | |
112 | FIELD(CPUCFG1, IOCSR, 3, 1) | |
113 | FIELD(CPUCFG1, PALEN, 4, 8) | |
114 | FIELD(CPUCFG1, VALEN, 12, 8) | |
115 | FIELD(CPUCFG1, UAL, 20, 1) | |
116 | FIELD(CPUCFG1, RI, 21, 1) | |
117 | FIELD(CPUCFG1, EP, 22, 1) | |
118 | FIELD(CPUCFG1, RPLV, 23, 1) | |
119 | FIELD(CPUCFG1, HP, 24, 1) | |
120 | FIELD(CPUCFG1, IOCSR_BRD, 25, 1) | |
121 | FIELD(CPUCFG1, MSG_INT, 26, 1) | |
122 | ||
123 | /* cpucfg[2] bits */ | |
124 | FIELD(CPUCFG2, FP, 0, 1) | |
125 | FIELD(CPUCFG2, FP_SP, 1, 1) | |
126 | FIELD(CPUCFG2, FP_DP, 2, 1) | |
127 | FIELD(CPUCFG2, FP_VER, 3, 3) | |
128 | FIELD(CPUCFG2, LSX, 6, 1) | |
129 | FIELD(CPUCFG2, LASX, 7, 1) | |
130 | FIELD(CPUCFG2, COMPLEX, 8, 1) | |
131 | FIELD(CPUCFG2, CRYPTO, 9, 1) | |
132 | FIELD(CPUCFG2, LVZ, 10, 1) | |
133 | FIELD(CPUCFG2, LVZ_VER, 11, 3) | |
134 | FIELD(CPUCFG2, LLFTP, 14, 1) | |
135 | FIELD(CPUCFG2, LLFTP_VER, 15, 3) | |
136 | FIELD(CPUCFG2, LBT_X86, 18, 1) | |
137 | FIELD(CPUCFG2, LBT_ARM, 19, 1) | |
138 | FIELD(CPUCFG2, LBT_MIPS, 20, 1) | |
139 | FIELD(CPUCFG2, LSPW, 21, 1) | |
140 | FIELD(CPUCFG2, LAM, 22, 1) | |
141 | ||
142 | /* cpucfg[3] bits */ | |
143 | FIELD(CPUCFG3, CCDMA, 0, 1) | |
144 | FIELD(CPUCFG3, SFB, 1, 1) | |
145 | FIELD(CPUCFG3, UCACC, 2, 1) | |
146 | FIELD(CPUCFG3, LLEXC, 3, 1) | |
147 | FIELD(CPUCFG3, SCDLY, 4, 1) | |
148 | FIELD(CPUCFG3, LLDBAR, 5, 1) | |
149 | FIELD(CPUCFG3, ITLBHMC, 6, 1) | |
150 | FIELD(CPUCFG3, ICHMC, 7, 1) | |
151 | FIELD(CPUCFG3, SPW_LVL, 8, 3) | |
152 | FIELD(CPUCFG3, SPW_HP_HF, 11, 1) | |
153 | FIELD(CPUCFG3, RVA, 12, 1) | |
154 | FIELD(CPUCFG3, RVAMAX, 13, 4) | |
155 | ||
156 | /* cpucfg[4] bits */ | |
157 | FIELD(CPUCFG4, CC_FREQ, 0, 32) | |
158 | ||
159 | /* cpucfg[5] bits */ | |
160 | FIELD(CPUCFG5, CC_MUL, 0, 16) | |
161 | FIELD(CPUCFG5, CC_DIV, 16, 16) | |
162 | ||
163 | /* cpucfg[6] bits */ | |
164 | FIELD(CPUCFG6, PMP, 0, 1) | |
165 | FIELD(CPUCFG6, PMVER, 1, 3) | |
166 | FIELD(CPUCFG6, PMNUM, 4, 4) | |
167 | FIELD(CPUCFG6, PMBITS, 8, 6) | |
168 | FIELD(CPUCFG6, UPM, 14, 1) | |
169 | ||
170 | /* cpucfg[16] bits */ | |
171 | FIELD(CPUCFG16, L1_IUPRE, 0, 1) | |
172 | FIELD(CPUCFG16, L1_IUUNIFY, 1, 1) | |
173 | FIELD(CPUCFG16, L1_DPRE, 2, 1) | |
174 | FIELD(CPUCFG16, L2_IUPRE, 3, 1) | |
175 | FIELD(CPUCFG16, L2_IUUNIFY, 4, 1) | |
176 | FIELD(CPUCFG16, L2_IUPRIV, 5, 1) | |
177 | FIELD(CPUCFG16, L2_IUINCL, 6, 1) | |
178 | FIELD(CPUCFG16, L2_DPRE, 7, 1) | |
179 | FIELD(CPUCFG16, L2_DPRIV, 8, 1) | |
180 | FIELD(CPUCFG16, L2_DINCL, 9, 1) | |
181 | FIELD(CPUCFG16, L3_IUPRE, 10, 1) | |
182 | FIELD(CPUCFG16, L3_IUUNIFY, 11, 1) | |
183 | FIELD(CPUCFG16, L3_IUPRIV, 12, 1) | |
184 | FIELD(CPUCFG16, L3_IUINCL, 13, 1) | |
185 | FIELD(CPUCFG16, L3_DPRE, 14, 1) | |
186 | FIELD(CPUCFG16, L3_DPRIV, 15, 1) | |
187 | FIELD(CPUCFG16, L3_DINCL, 16, 1) | |
188 | ||
189 | /* cpucfg[17] bits */ | |
190 | FIELD(CPUCFG17, L1IU_WAYS, 0, 16) | |
191 | FIELD(CPUCFG17, L1IU_SETS, 16, 8) | |
192 | FIELD(CPUCFG17, L1IU_SIZE, 24, 7) | |
193 | ||
194 | /* cpucfg[18] bits */ | |
195 | FIELD(CPUCFG18, L1D_WAYS, 0, 16) | |
196 | FIELD(CPUCFG18, L1D_SETS, 16, 8) | |
197 | FIELD(CPUCFG18, L1D_SIZE, 24, 7) | |
198 | ||
199 | /* cpucfg[19] bits */ | |
200 | FIELD(CPUCFG19, L2IU_WAYS, 0, 16) | |
201 | FIELD(CPUCFG19, L2IU_SETS, 16, 8) | |
202 | FIELD(CPUCFG19, L2IU_SIZE, 24, 7) | |
203 | ||
204 | /* cpucfg[20] bits */ | |
205 | FIELD(CPUCFG20, L3IU_WAYS, 0, 16) | |
206 | FIELD(CPUCFG20, L3IU_SETS, 16, 8) | |
207 | FIELD(CPUCFG20, L3IU_SIZE, 24, 7) | |
208 | ||
398cecb9 XY |
209 | /*CSR_CRMD */ |
210 | FIELD(CSR_CRMD, PLV, 0, 2) | |
211 | FIELD(CSR_CRMD, IE, 2, 1) | |
212 | FIELD(CSR_CRMD, DA, 3, 1) | |
213 | FIELD(CSR_CRMD, PG, 4, 1) | |
214 | FIELD(CSR_CRMD, DATF, 5, 2) | |
215 | FIELD(CSR_CRMD, DATM, 7, 2) | |
216 | FIELD(CSR_CRMD, WE, 9, 1) | |
217 | ||
228021f0 SG |
218 | extern const char * const regnames[32]; |
219 | extern const char * const fregnames[32]; | |
220 | ||
f757a2cd | 221 | #define N_IRQS 13 |
dd615fa4 XY |
222 | #define IRQ_TIMER 11 |
223 | #define IRQ_IPI 12 | |
f757a2cd | 224 | |
7e1c521e XY |
225 | #define LOONGARCH_STLB 2048 /* 2048 STLB */ |
226 | #define LOONGARCH_MTLB 64 /* 64 MTLB */ | |
227 | #define LOONGARCH_TLB_MAX (LOONGARCH_STLB + LOONGARCH_MTLB) | |
228 | ||
229 | /* | |
230 | * define the ASID PS E VPPN field of TLB | |
231 | */ | |
232 | FIELD(TLB_MISC, E, 0, 1) | |
233 | FIELD(TLB_MISC, ASID, 1, 10) | |
234 | FIELD(TLB_MISC, VPPN, 13, 35) | |
235 | FIELD(TLB_MISC, PS, 48, 6) | |
236 | ||
237 | struct LoongArchTLB { | |
238 | uint64_t tlb_misc; | |
239 | /* Fields corresponding to CSR_TLBELO0/1 */ | |
240 | uint64_t tlb_entry0; | |
241 | uint64_t tlb_entry1; | |
242 | }; | |
243 | typedef struct LoongArchTLB LoongArchTLB; | |
244 | ||
228021f0 SG |
245 | typedef struct CPUArchState { |
246 | uint64_t gpr[32]; | |
247 | uint64_t pc; | |
248 | ||
249 | uint64_t fpr[32]; | |
250 | float_status fp_status; | |
251 | bool cf[8]; | |
252 | ||
253 | uint32_t fcsr0; | |
254 | uint32_t fcsr0_mask; | |
255 | ||
256 | uint32_t cpucfg[21]; | |
257 | ||
258 | uint64_t lladdr; /* LL virtual address compared against SC */ | |
259 | uint64_t llval; | |
260 | ||
398cecb9 XY |
261 | /* LoongArch CSRs */ |
262 | uint64_t CSR_CRMD; | |
263 | uint64_t CSR_PRMD; | |
264 | uint64_t CSR_EUEN; | |
265 | uint64_t CSR_MISC; | |
266 | uint64_t CSR_ECFG; | |
267 | uint64_t CSR_ESTAT; | |
268 | uint64_t CSR_ERA; | |
269 | uint64_t CSR_BADV; | |
270 | uint64_t CSR_BADI; | |
271 | uint64_t CSR_EENTRY; | |
272 | uint64_t CSR_TLBIDX; | |
273 | uint64_t CSR_TLBEHI; | |
274 | uint64_t CSR_TLBELO0; | |
275 | uint64_t CSR_TLBELO1; | |
276 | uint64_t CSR_ASID; | |
277 | uint64_t CSR_PGDL; | |
278 | uint64_t CSR_PGDH; | |
279 | uint64_t CSR_PGD; | |
280 | uint64_t CSR_PWCL; | |
281 | uint64_t CSR_PWCH; | |
282 | uint64_t CSR_STLBPS; | |
283 | uint64_t CSR_RVACFG; | |
284 | uint64_t CSR_PRCFG1; | |
285 | uint64_t CSR_PRCFG2; | |
286 | uint64_t CSR_PRCFG3; | |
287 | uint64_t CSR_SAVE[16]; | |
288 | uint64_t CSR_TID; | |
289 | uint64_t CSR_TCFG; | |
290 | uint64_t CSR_TVAL; | |
291 | uint64_t CSR_CNTC; | |
292 | uint64_t CSR_TICLR; | |
293 | uint64_t CSR_LLBCTL; | |
294 | uint64_t CSR_IMPCTL1; | |
295 | uint64_t CSR_IMPCTL2; | |
296 | uint64_t CSR_TLBRENTRY; | |
297 | uint64_t CSR_TLBRBADV; | |
298 | uint64_t CSR_TLBRERA; | |
299 | uint64_t CSR_TLBRSAVE; | |
300 | uint64_t CSR_TLBRELO0; | |
301 | uint64_t CSR_TLBRELO1; | |
302 | uint64_t CSR_TLBREHI; | |
303 | uint64_t CSR_TLBRPRMD; | |
304 | uint64_t CSR_MERRCTL; | |
305 | uint64_t CSR_MERRINFO1; | |
306 | uint64_t CSR_MERRINFO2; | |
307 | uint64_t CSR_MERRENTRY; | |
308 | uint64_t CSR_MERRERA; | |
309 | uint64_t CSR_MERRSAVE; | |
310 | uint64_t CSR_CTAG; | |
311 | uint64_t CSR_DMW[4]; | |
312 | uint64_t CSR_DBG; | |
313 | uint64_t CSR_DERA; | |
314 | uint64_t CSR_DSAVE; | |
7e1c521e | 315 | |
0093b9a5 | 316 | #ifndef CONFIG_USER_ONLY |
7e1c521e | 317 | LoongArchTLB tlb[LOONGARCH_TLB_MAX]; |
f84a2aac XY |
318 | |
319 | AddressSpace address_space_iocsr; | |
320 | MemoryRegion system_iocsr; | |
321 | MemoryRegion iocsr_mem; | |
6a6f26f4 XY |
322 | bool load_elf; |
323 | uint64_t elf_address; | |
0093b9a5 | 324 | #endif |
228021f0 SG |
325 | } CPULoongArchState; |
326 | ||
327 | /** | |
328 | * LoongArchCPU: | |
329 | * @env: #CPULoongArchState | |
330 | * | |
331 | * A LoongArch CPU. | |
332 | */ | |
333 | struct ArchCPU { | |
334 | /*< private >*/ | |
335 | CPUState parent_obj; | |
336 | /*< public >*/ | |
337 | ||
338 | CPUNegativeOffsetState neg; | |
339 | CPULoongArchState env; | |
dd615fa4 | 340 | QEMUTimer timer; |
fda3f15b XY |
341 | |
342 | /* 'compatible' string for this CPU for Linux device trees */ | |
343 | const char *dtb_compatible; | |
228021f0 SG |
344 | }; |
345 | ||
346 | #define TYPE_LOONGARCH_CPU "loongarch-cpu" | |
347 | ||
348 | OBJECT_DECLARE_CPU_TYPE(LoongArchCPU, LoongArchCPUClass, | |
349 | LOONGARCH_CPU) | |
350 | ||
351 | /** | |
352 | * LoongArchCPUClass: | |
353 | * @parent_realize: The parent class' realize handler. | |
354 | * @parent_reset: The parent class' reset handler. | |
355 | * | |
356 | * A LoongArch CPU model. | |
357 | */ | |
358 | struct LoongArchCPUClass { | |
359 | /*< private >*/ | |
360 | CPUClass parent_class; | |
361 | /*< public >*/ | |
362 | ||
363 | DeviceRealize parent_realize; | |
364 | DeviceReset parent_reset; | |
365 | }; | |
366 | ||
7e1c521e XY |
367 | /* |
368 | * LoongArch CPUs has 4 privilege levels. | |
369 | * 0 for kernel mode, 3 for user mode. | |
370 | * Define an extra index for DA(direct addressing) mode. | |
371 | */ | |
372 | #define MMU_KERNEL_IDX 0 | |
373 | #define MMU_USER_IDX 3 | |
374 | #define MMU_DA_IDX 4 | |
375 | ||
376 | static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) | |
377 | { | |
0093b9a5 SG |
378 | #ifdef CONFIG_USER_ONLY |
379 | return MMU_USER_IDX; | |
380 | #else | |
7e1c521e XY |
381 | uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG); |
382 | ||
383 | if (!pg) { | |
384 | return MMU_DA_IDX; | |
385 | } | |
386 | return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); | |
0093b9a5 | 387 | #endif |
7e1c521e XY |
388 | } |
389 | ||
390 | static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, | |
391 | target_ulong *pc, | |
392 | target_ulong *cs_base, | |
393 | uint32_t *flags) | |
394 | { | |
395 | *pc = env->pc; | |
396 | *cs_base = 0; | |
397 | *flags = cpu_mmu_index(env, false); | |
398 | } | |
399 | ||
228021f0 SG |
400 | void loongarch_cpu_list(void); |
401 | ||
402 | #define cpu_list loongarch_cpu_list | |
403 | ||
404 | #include "exec/cpu-all.h" | |
405 | ||
406 | #define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU | |
407 | #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX | |
408 | #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU | |
409 | ||
410 | #endif /* LOONGARCH_CPU_H */ |