xref: /qemu/target/loongarch/cpu.h (revision edcea147e342a2ae1cb45a3beb40b428f93b1d1c)
1228021f0SSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
2228021f0SSong Gao /*
3228021f0SSong Gao  * QEMU LoongArch CPU
4228021f0SSong Gao  *
5228021f0SSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
6228021f0SSong Gao  */
7228021f0SSong Gao 
8228021f0SSong Gao #ifndef LOONGARCH_CPU_H
9228021f0SSong Gao #define LOONGARCH_CPU_H
10228021f0SSong Gao 
1116f5396cSSong Gao #include "qemu/int128.h"
12228021f0SSong Gao #include "exec/cpu-defs.h"
13228021f0SSong Gao #include "fpu/softfloat-types.h"
14228021f0SSong Gao #include "hw/registerfields.h"
15dd615fa4SXiaojuan Yang #include "qemu/timer.h"
168f15d617SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
17f84a2aacSXiaojuan Yang #include "exec/memory.h"
188f15d617SPhilippe Mathieu-Daudé #endif
19b4bda200SRui Wang #include "cpu-csr.h"
20*edcea147SPhilippe Mathieu-Daudé #include "cpu-qom.h"
21f84a2aacSXiaojuan Yang 
22f84a2aacSXiaojuan Yang #define IOCSRF_TEMP             0
23f84a2aacSXiaojuan Yang #define IOCSRF_NODECNT          1
24f84a2aacSXiaojuan Yang #define IOCSRF_MSI              2
25f84a2aacSXiaojuan Yang #define IOCSRF_EXTIOI           3
26f84a2aacSXiaojuan Yang #define IOCSRF_CSRIPI           4
27f84a2aacSXiaojuan Yang #define IOCSRF_FREQCSR          5
28f84a2aacSXiaojuan Yang #define IOCSRF_FREQSCALE        6
29f84a2aacSXiaojuan Yang #define IOCSRF_DVFSV1           7
30f84a2aacSXiaojuan Yang #define IOCSRF_GMOD             9
31f84a2aacSXiaojuan Yang #define IOCSRF_VM               11
32f84a2aacSXiaojuan Yang 
33c77432d0SSong Gao #define VERSION_REG             0x0
34f84a2aacSXiaojuan Yang #define FEATURE_REG             0x8
35f84a2aacSXiaojuan Yang #define VENDOR_REG              0x10
36f84a2aacSXiaojuan Yang #define CPUNAME_REG             0x20
37f84a2aacSXiaojuan Yang #define MISC_FUNC_REG           0x420
38f84a2aacSXiaojuan Yang #define IOCSRM_EXTIOI_EN        48
39f84a2aacSXiaojuan Yang 
40f84a2aacSXiaojuan Yang #define IOCSR_MEM_SIZE          0x428
41228021f0SSong Gao 
42228021f0SSong Gao #define TCG_GUEST_DEFAULT_MO (0)
43228021f0SSong Gao 
44228021f0SSong Gao #define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
45228021f0SSong Gao #define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
46228021f0SSong Gao #define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
47228021f0SSong Gao #define FCSR0_RM    8            /* Round Mode bit num on fcsr0 */
48228021f0SSong Gao 
49228021f0SSong Gao FIELD(FCSR0, ENABLES, 0, 5)
50228021f0SSong Gao FIELD(FCSR0, RM, 8, 2)
51228021f0SSong Gao FIELD(FCSR0, FLAGS, 16, 5)
52228021f0SSong Gao FIELD(FCSR0, CAUSE, 24, 5)
53228021f0SSong Gao 
54228021f0SSong Gao #define GET_FP_CAUSE(REG)      FIELD_EX32(REG, FCSR0, CAUSE)
5500952d93SQi Hu #define SET_FP_CAUSE(REG, V) \
5600952d93SQi Hu     do { \
5700952d93SQi Hu         (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \
5800952d93SQi Hu     } while (0)
59aca67472SSong Gao #define UPDATE_FP_CAUSE(REG, V) \
60aca67472SSong Gao     do { \
61aca67472SSong Gao         (REG) |= FIELD_DP32(0, FCSR0, CAUSE, V); \
62aca67472SSong Gao     } while (0)
6300952d93SQi Hu 
64228021f0SSong Gao #define GET_FP_ENABLES(REG)    FIELD_EX32(REG, FCSR0, ENABLES)
6500952d93SQi Hu #define SET_FP_ENABLES(REG, V) \
6600952d93SQi Hu     do { \
6700952d93SQi Hu         (REG) = FIELD_DP32(REG, FCSR0, ENABLES, V); \
6800952d93SQi Hu     } while (0)
6900952d93SQi Hu 
70228021f0SSong Gao #define GET_FP_FLAGS(REG)      FIELD_EX32(REG, FCSR0, FLAGS)
7100952d93SQi Hu #define SET_FP_FLAGS(REG, V) \
7200952d93SQi Hu     do { \
7300952d93SQi Hu         (REG) = FIELD_DP32(REG, FCSR0, FLAGS, V); \
7400952d93SQi Hu     } while (0)
7500952d93SQi Hu 
76228021f0SSong Gao #define UPDATE_FP_FLAGS(REG, V) \
77228021f0SSong Gao     do { \
78228021f0SSong Gao         (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \
79228021f0SSong Gao     } while (0)
80228021f0SSong Gao 
81228021f0SSong Gao #define FP_INEXACT        1
82228021f0SSong Gao #define FP_UNDERFLOW      2
83228021f0SSong Gao #define FP_OVERFLOW       4
84228021f0SSong Gao #define FP_DIV0           8
85228021f0SSong Gao #define FP_INVALID        16
86228021f0SSong Gao 
87a6b129c8SSong Gao #define EXCODE(code, subcode) ( ((subcode) << 6) | (code) )
88a6b129c8SSong Gao #define EXCODE_MCODE(code)    ( (code) & 0x3f )
89a6b129c8SSong Gao #define EXCODE_SUBCODE(code)  ( (code) >> 6 )
90a6b129c8SSong Gao 
91228021f0SSong Gao #define  EXCCODE_EXTERNAL_INT        64   /* plus external interrupt number */
92a6b129c8SSong Gao #define  EXCCODE_INT                 EXCODE(0, 0)
93a6b129c8SSong Gao #define  EXCCODE_PIL                 EXCODE(1, 0)
94a6b129c8SSong Gao #define  EXCCODE_PIS                 EXCODE(2, 0)
95a6b129c8SSong Gao #define  EXCCODE_PIF                 EXCODE(3, 0)
96a6b129c8SSong Gao #define  EXCCODE_PME                 EXCODE(4, 0)
97a6b129c8SSong Gao #define  EXCCODE_PNR                 EXCODE(5, 0)
98a6b129c8SSong Gao #define  EXCCODE_PNX                 EXCODE(6, 0)
99a6b129c8SSong Gao #define  EXCCODE_PPI                 EXCODE(7, 0)
100a6b129c8SSong Gao #define  EXCCODE_ADEF                EXCODE(8, 0) /* Different exception subcode */
101a6b129c8SSong Gao #define  EXCCODE_ADEM                EXCODE(8, 1)
102a6b129c8SSong Gao #define  EXCCODE_ALE                 EXCODE(9, 0)
103a6b129c8SSong Gao #define  EXCCODE_BCE                 EXCODE(10, 0)
104a6b129c8SSong Gao #define  EXCCODE_SYS                 EXCODE(11, 0)
105a6b129c8SSong Gao #define  EXCCODE_BRK                 EXCODE(12, 0)
106a6b129c8SSong Gao #define  EXCCODE_INE                 EXCODE(13, 0)
107a6b129c8SSong Gao #define  EXCCODE_IPE                 EXCODE(14, 0)
108a6b129c8SSong Gao #define  EXCCODE_FPD                 EXCODE(15, 0)
109a6b129c8SSong Gao #define  EXCCODE_SXD                 EXCODE(16, 0)
110a6b129c8SSong Gao #define  EXCCODE_ASXD                EXCODE(17, 0)
111a6b129c8SSong Gao #define  EXCCODE_FPE                 EXCODE(18, 0) /* Different exception subcode */
112a6b129c8SSong Gao #define  EXCCODE_VFPE                EXCODE(18, 1)
113a6b129c8SSong Gao #define  EXCCODE_WPEF                EXCODE(19, 0) /* Different exception subcode */
114a6b129c8SSong Gao #define  EXCCODE_WPEM                EXCODE(19, 1)
115a6b129c8SSong Gao #define  EXCCODE_BTD                 EXCODE(20, 0)
116a6b129c8SSong Gao #define  EXCCODE_BTE                 EXCODE(21, 0)
117a6b129c8SSong Gao #define  EXCCODE_DBP                 EXCODE(26, 0) /* Reserved subcode used for debug */
118228021f0SSong Gao 
119228021f0SSong Gao /* cpucfg[0] bits */
120228021f0SSong Gao FIELD(CPUCFG0, PRID, 0, 32)
121228021f0SSong Gao 
122228021f0SSong Gao /* cpucfg[1] bits */
123228021f0SSong Gao FIELD(CPUCFG1, ARCH, 0, 2)
124228021f0SSong Gao FIELD(CPUCFG1, PGMMU, 2, 1)
125228021f0SSong Gao FIELD(CPUCFG1, IOCSR, 3, 1)
126228021f0SSong Gao FIELD(CPUCFG1, PALEN, 4, 8)
127228021f0SSong Gao FIELD(CPUCFG1, VALEN, 12, 8)
128228021f0SSong Gao FIELD(CPUCFG1, UAL, 20, 1)
129228021f0SSong Gao FIELD(CPUCFG1, RI, 21, 1)
130228021f0SSong Gao FIELD(CPUCFG1, EP, 22, 1)
131228021f0SSong Gao FIELD(CPUCFG1, RPLV, 23, 1)
132228021f0SSong Gao FIELD(CPUCFG1, HP, 24, 1)
133228021f0SSong Gao FIELD(CPUCFG1, IOCSR_BRD, 25, 1)
134228021f0SSong Gao FIELD(CPUCFG1, MSG_INT, 26, 1)
135228021f0SSong Gao 
13619f82a4aSJiajie Chen /* cpucfg[1].arch */
13719f82a4aSJiajie Chen #define CPUCFG1_ARCH_LA32R       0
13819f82a4aSJiajie Chen #define CPUCFG1_ARCH_LA32        1
13919f82a4aSJiajie Chen #define CPUCFG1_ARCH_LA64        2
14019f82a4aSJiajie Chen 
141228021f0SSong Gao /* cpucfg[2] bits */
142228021f0SSong Gao FIELD(CPUCFG2, FP, 0, 1)
143228021f0SSong Gao FIELD(CPUCFG2, FP_SP, 1, 1)
144228021f0SSong Gao FIELD(CPUCFG2, FP_DP, 2, 1)
145228021f0SSong Gao FIELD(CPUCFG2, FP_VER, 3, 3)
146228021f0SSong Gao FIELD(CPUCFG2, LSX, 6, 1)
147228021f0SSong Gao FIELD(CPUCFG2, LASX, 7, 1)
148228021f0SSong Gao FIELD(CPUCFG2, COMPLEX, 8, 1)
149228021f0SSong Gao FIELD(CPUCFG2, CRYPTO, 9, 1)
150228021f0SSong Gao FIELD(CPUCFG2, LVZ, 10, 1)
151228021f0SSong Gao FIELD(CPUCFG2, LVZ_VER, 11, 3)
152228021f0SSong Gao FIELD(CPUCFG2, LLFTP, 14, 1)
153228021f0SSong Gao FIELD(CPUCFG2, LLFTP_VER, 15, 3)
154228021f0SSong Gao FIELD(CPUCFG2, LBT_X86, 18, 1)
155228021f0SSong Gao FIELD(CPUCFG2, LBT_ARM, 19, 1)
156228021f0SSong Gao FIELD(CPUCFG2, LBT_MIPS, 20, 1)
157228021f0SSong Gao FIELD(CPUCFG2, LSPW, 21, 1)
158228021f0SSong Gao FIELD(CPUCFG2, LAM, 22, 1)
159228021f0SSong Gao 
160228021f0SSong Gao /* cpucfg[3] bits */
161228021f0SSong Gao FIELD(CPUCFG3, CCDMA, 0, 1)
162228021f0SSong Gao FIELD(CPUCFG3, SFB, 1, 1)
163228021f0SSong Gao FIELD(CPUCFG3, UCACC, 2, 1)
164228021f0SSong Gao FIELD(CPUCFG3, LLEXC, 3, 1)
165228021f0SSong Gao FIELD(CPUCFG3, SCDLY, 4, 1)
166228021f0SSong Gao FIELD(CPUCFG3, LLDBAR, 5, 1)
167228021f0SSong Gao FIELD(CPUCFG3, ITLBHMC, 6, 1)
168228021f0SSong Gao FIELD(CPUCFG3, ICHMC, 7, 1)
169228021f0SSong Gao FIELD(CPUCFG3, SPW_LVL, 8, 3)
170228021f0SSong Gao FIELD(CPUCFG3, SPW_HP_HF, 11, 1)
171228021f0SSong Gao FIELD(CPUCFG3, RVA, 12, 1)
172228021f0SSong Gao FIELD(CPUCFG3, RVAMAX, 13, 4)
173228021f0SSong Gao 
174228021f0SSong Gao /* cpucfg[4] bits */
175228021f0SSong Gao FIELD(CPUCFG4, CC_FREQ, 0, 32)
176228021f0SSong Gao 
177228021f0SSong Gao /* cpucfg[5] bits */
178228021f0SSong Gao FIELD(CPUCFG5, CC_MUL, 0, 16)
179228021f0SSong Gao FIELD(CPUCFG5, CC_DIV, 16, 16)
180228021f0SSong Gao 
181228021f0SSong Gao /* cpucfg[6] bits */
182228021f0SSong Gao FIELD(CPUCFG6, PMP, 0, 1)
183228021f0SSong Gao FIELD(CPUCFG6, PMVER, 1, 3)
184228021f0SSong Gao FIELD(CPUCFG6, PMNUM, 4, 4)
185228021f0SSong Gao FIELD(CPUCFG6, PMBITS, 8, 6)
186228021f0SSong Gao FIELD(CPUCFG6, UPM, 14, 1)
187228021f0SSong Gao 
188228021f0SSong Gao /* cpucfg[16] bits */
189228021f0SSong Gao FIELD(CPUCFG16, L1_IUPRE, 0, 1)
190228021f0SSong Gao FIELD(CPUCFG16, L1_IUUNIFY, 1, 1)
191228021f0SSong Gao FIELD(CPUCFG16, L1_DPRE, 2, 1)
192228021f0SSong Gao FIELD(CPUCFG16, L2_IUPRE, 3, 1)
193228021f0SSong Gao FIELD(CPUCFG16, L2_IUUNIFY, 4, 1)
194228021f0SSong Gao FIELD(CPUCFG16, L2_IUPRIV, 5, 1)
195228021f0SSong Gao FIELD(CPUCFG16, L2_IUINCL, 6, 1)
196228021f0SSong Gao FIELD(CPUCFG16, L2_DPRE, 7, 1)
197228021f0SSong Gao FIELD(CPUCFG16, L2_DPRIV, 8, 1)
198228021f0SSong Gao FIELD(CPUCFG16, L2_DINCL, 9, 1)
199228021f0SSong Gao FIELD(CPUCFG16, L3_IUPRE, 10, 1)
200228021f0SSong Gao FIELD(CPUCFG16, L3_IUUNIFY, 11, 1)
201228021f0SSong Gao FIELD(CPUCFG16, L3_IUPRIV, 12, 1)
202228021f0SSong Gao FIELD(CPUCFG16, L3_IUINCL, 13, 1)
203228021f0SSong Gao FIELD(CPUCFG16, L3_DPRE, 14, 1)
204228021f0SSong Gao FIELD(CPUCFG16, L3_DPRIV, 15, 1)
205228021f0SSong Gao FIELD(CPUCFG16, L3_DINCL, 16, 1)
206228021f0SSong Gao 
207228021f0SSong Gao /* cpucfg[17] bits */
208228021f0SSong Gao FIELD(CPUCFG17, L1IU_WAYS, 0, 16)
209228021f0SSong Gao FIELD(CPUCFG17, L1IU_SETS, 16, 8)
210228021f0SSong Gao FIELD(CPUCFG17, L1IU_SIZE, 24, 7)
211228021f0SSong Gao 
212228021f0SSong Gao /* cpucfg[18] bits */
213228021f0SSong Gao FIELD(CPUCFG18, L1D_WAYS, 0, 16)
214228021f0SSong Gao FIELD(CPUCFG18, L1D_SETS, 16, 8)
215228021f0SSong Gao FIELD(CPUCFG18, L1D_SIZE, 24, 7)
216228021f0SSong Gao 
217228021f0SSong Gao /* cpucfg[19] bits */
218228021f0SSong Gao FIELD(CPUCFG19, L2IU_WAYS, 0, 16)
219228021f0SSong Gao FIELD(CPUCFG19, L2IU_SETS, 16, 8)
220228021f0SSong Gao FIELD(CPUCFG19, L2IU_SIZE, 24, 7)
221228021f0SSong Gao 
222228021f0SSong Gao /* cpucfg[20] bits */
223228021f0SSong Gao FIELD(CPUCFG20, L3IU_WAYS, 0, 16)
224228021f0SSong Gao FIELD(CPUCFG20, L3IU_SETS, 16, 8)
225228021f0SSong Gao FIELD(CPUCFG20, L3IU_SIZE, 24, 7)
226228021f0SSong Gao 
227398cecb9SXiaojuan Yang /*CSR_CRMD */
228398cecb9SXiaojuan Yang FIELD(CSR_CRMD, PLV, 0, 2)
229398cecb9SXiaojuan Yang FIELD(CSR_CRMD, IE, 2, 1)
230398cecb9SXiaojuan Yang FIELD(CSR_CRMD, DA, 3, 1)
231398cecb9SXiaojuan Yang FIELD(CSR_CRMD, PG, 4, 1)
232398cecb9SXiaojuan Yang FIELD(CSR_CRMD, DATF, 5, 2)
233398cecb9SXiaojuan Yang FIELD(CSR_CRMD, DATM, 7, 2)
234398cecb9SXiaojuan Yang FIELD(CSR_CRMD, WE, 9, 1)
235398cecb9SXiaojuan Yang 
236228021f0SSong Gao extern const char * const regnames[32];
237228021f0SSong Gao extern const char * const fregnames[32];
238228021f0SSong Gao 
239f757a2cdSXiaojuan Yang #define N_IRQS      13
240dd615fa4SXiaojuan Yang #define IRQ_TIMER   11
241dd615fa4SXiaojuan Yang #define IRQ_IPI     12
242f757a2cdSXiaojuan Yang 
2437e1c521eSXiaojuan Yang #define LOONGARCH_STLB         2048 /* 2048 STLB */
2447e1c521eSXiaojuan Yang #define LOONGARCH_MTLB         64   /* 64 MTLB */
2457e1c521eSXiaojuan Yang #define LOONGARCH_TLB_MAX      (LOONGARCH_STLB + LOONGARCH_MTLB)
2467e1c521eSXiaojuan Yang 
2477e1c521eSXiaojuan Yang /*
2487e1c521eSXiaojuan Yang  * define the ASID PS E VPPN field of TLB
2497e1c521eSXiaojuan Yang  */
2507e1c521eSXiaojuan Yang FIELD(TLB_MISC, E, 0, 1)
2517e1c521eSXiaojuan Yang FIELD(TLB_MISC, ASID, 1, 10)
2527e1c521eSXiaojuan Yang FIELD(TLB_MISC, VPPN, 13, 35)
2537e1c521eSXiaojuan Yang FIELD(TLB_MISC, PS, 48, 6)
2547e1c521eSXiaojuan Yang 
25516f5396cSSong Gao #define LSX_LEN    (128)
256008a3b16SSong Gao #define LASX_LEN   (256)
257008a3b16SSong Gao 
25816f5396cSSong Gao typedef union VReg {
259008a3b16SSong Gao     int8_t   B[LASX_LEN / 8];
260008a3b16SSong Gao     int16_t  H[LASX_LEN / 16];
261008a3b16SSong Gao     int32_t  W[LASX_LEN / 32];
262008a3b16SSong Gao     int64_t  D[LASX_LEN / 64];
263008a3b16SSong Gao     uint8_t  UB[LASX_LEN / 8];
264008a3b16SSong Gao     uint16_t UH[LASX_LEN / 16];
265008a3b16SSong Gao     uint32_t UW[LASX_LEN / 32];
266008a3b16SSong Gao     uint64_t UD[LASX_LEN / 64];
267008a3b16SSong Gao     Int128   Q[LASX_LEN / 128];
26816f5396cSSong Gao } VReg;
26916f5396cSSong Gao 
27016f5396cSSong Gao typedef union fpr_t fpr_t;
27116f5396cSSong Gao union fpr_t {
27216f5396cSSong Gao     VReg  vreg;
27316f5396cSSong Gao };
27416f5396cSSong Gao 
2757e1c521eSXiaojuan Yang struct LoongArchTLB {
2767e1c521eSXiaojuan Yang     uint64_t tlb_misc;
2777e1c521eSXiaojuan Yang     /* Fields corresponding to CSR_TLBELO0/1 */
2787e1c521eSXiaojuan Yang     uint64_t tlb_entry0;
2797e1c521eSXiaojuan Yang     uint64_t tlb_entry1;
2807e1c521eSXiaojuan Yang };
2817e1c521eSXiaojuan Yang typedef struct LoongArchTLB LoongArchTLB;
2827e1c521eSXiaojuan Yang 
283228021f0SSong Gao typedef struct CPUArchState {
284228021f0SSong Gao     uint64_t gpr[32];
285228021f0SSong Gao     uint64_t pc;
286228021f0SSong Gao 
28716f5396cSSong Gao     fpr_t fpr[32];
288228021f0SSong Gao     float_status fp_status;
289228021f0SSong Gao     bool cf[8];
290228021f0SSong Gao 
291228021f0SSong Gao     uint32_t fcsr0;
292228021f0SSong Gao     uint32_t fcsr0_mask;
293228021f0SSong Gao 
294228021f0SSong Gao     uint32_t cpucfg[21];
295228021f0SSong Gao 
296228021f0SSong Gao     uint64_t lladdr; /* LL virtual address compared against SC */
297228021f0SSong Gao     uint64_t llval;
298228021f0SSong Gao 
299398cecb9SXiaojuan Yang     /* LoongArch CSRs */
300398cecb9SXiaojuan Yang     uint64_t CSR_CRMD;
301398cecb9SXiaojuan Yang     uint64_t CSR_PRMD;
302398cecb9SXiaojuan Yang     uint64_t CSR_EUEN;
303398cecb9SXiaojuan Yang     uint64_t CSR_MISC;
304398cecb9SXiaojuan Yang     uint64_t CSR_ECFG;
305398cecb9SXiaojuan Yang     uint64_t CSR_ESTAT;
306398cecb9SXiaojuan Yang     uint64_t CSR_ERA;
307398cecb9SXiaojuan Yang     uint64_t CSR_BADV;
308398cecb9SXiaojuan Yang     uint64_t CSR_BADI;
309398cecb9SXiaojuan Yang     uint64_t CSR_EENTRY;
310398cecb9SXiaojuan Yang     uint64_t CSR_TLBIDX;
311398cecb9SXiaojuan Yang     uint64_t CSR_TLBEHI;
312398cecb9SXiaojuan Yang     uint64_t CSR_TLBELO0;
313398cecb9SXiaojuan Yang     uint64_t CSR_TLBELO1;
314398cecb9SXiaojuan Yang     uint64_t CSR_ASID;
315398cecb9SXiaojuan Yang     uint64_t CSR_PGDL;
316398cecb9SXiaojuan Yang     uint64_t CSR_PGDH;
317398cecb9SXiaojuan Yang     uint64_t CSR_PGD;
318398cecb9SXiaojuan Yang     uint64_t CSR_PWCL;
319398cecb9SXiaojuan Yang     uint64_t CSR_PWCH;
320398cecb9SXiaojuan Yang     uint64_t CSR_STLBPS;
321398cecb9SXiaojuan Yang     uint64_t CSR_RVACFG;
322398cecb9SXiaojuan Yang     uint64_t CSR_PRCFG1;
323398cecb9SXiaojuan Yang     uint64_t CSR_PRCFG2;
324398cecb9SXiaojuan Yang     uint64_t CSR_PRCFG3;
325398cecb9SXiaojuan Yang     uint64_t CSR_SAVE[16];
326398cecb9SXiaojuan Yang     uint64_t CSR_TID;
327398cecb9SXiaojuan Yang     uint64_t CSR_TCFG;
328398cecb9SXiaojuan Yang     uint64_t CSR_TVAL;
329398cecb9SXiaojuan Yang     uint64_t CSR_CNTC;
330398cecb9SXiaojuan Yang     uint64_t CSR_TICLR;
331398cecb9SXiaojuan Yang     uint64_t CSR_LLBCTL;
332398cecb9SXiaojuan Yang     uint64_t CSR_IMPCTL1;
333398cecb9SXiaojuan Yang     uint64_t CSR_IMPCTL2;
334398cecb9SXiaojuan Yang     uint64_t CSR_TLBRENTRY;
335398cecb9SXiaojuan Yang     uint64_t CSR_TLBRBADV;
336398cecb9SXiaojuan Yang     uint64_t CSR_TLBRERA;
337398cecb9SXiaojuan Yang     uint64_t CSR_TLBRSAVE;
338398cecb9SXiaojuan Yang     uint64_t CSR_TLBRELO0;
339398cecb9SXiaojuan Yang     uint64_t CSR_TLBRELO1;
340398cecb9SXiaojuan Yang     uint64_t CSR_TLBREHI;
341398cecb9SXiaojuan Yang     uint64_t CSR_TLBRPRMD;
342398cecb9SXiaojuan Yang     uint64_t CSR_MERRCTL;
343398cecb9SXiaojuan Yang     uint64_t CSR_MERRINFO1;
344398cecb9SXiaojuan Yang     uint64_t CSR_MERRINFO2;
345398cecb9SXiaojuan Yang     uint64_t CSR_MERRENTRY;
346398cecb9SXiaojuan Yang     uint64_t CSR_MERRERA;
347398cecb9SXiaojuan Yang     uint64_t CSR_MERRSAVE;
348398cecb9SXiaojuan Yang     uint64_t CSR_CTAG;
349398cecb9SXiaojuan Yang     uint64_t CSR_DMW[4];
350398cecb9SXiaojuan Yang     uint64_t CSR_DBG;
351398cecb9SXiaojuan Yang     uint64_t CSR_DERA;
352398cecb9SXiaojuan Yang     uint64_t CSR_DSAVE;
353c34ad459SThomas Huth     uint64_t CSR_CPUID;
3547e1c521eSXiaojuan Yang 
3550093b9a5SSong Gao #ifndef CONFIG_USER_ONLY
3567e1c521eSXiaojuan Yang     LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
357f84a2aacSXiaojuan Yang 
358f84a2aacSXiaojuan Yang     AddressSpace address_space_iocsr;
359f84a2aacSXiaojuan Yang     MemoryRegion system_iocsr;
360f84a2aacSXiaojuan Yang     MemoryRegion iocsr_mem;
3616a6f26f4SXiaojuan Yang     bool load_elf;
3626a6f26f4SXiaojuan Yang     uint64_t elf_address;
363758a7475STianrui Zhao     /* Store ipistate to access from this struct */
364758a7475STianrui Zhao     DeviceState *ipistate;
3650093b9a5SSong Gao #endif
366228021f0SSong Gao } CPULoongArchState;
367228021f0SSong Gao 
368228021f0SSong Gao /**
369228021f0SSong Gao  * LoongArchCPU:
370228021f0SSong Gao  * @env: #CPULoongArchState
371228021f0SSong Gao  *
372228021f0SSong Gao  * A LoongArch CPU.
373228021f0SSong Gao  */
374228021f0SSong Gao struct ArchCPU {
375228021f0SSong Gao     CPUState parent_obj;
376228021f0SSong Gao 
377228021f0SSong Gao     CPULoongArchState env;
378dd615fa4SXiaojuan Yang     QEMUTimer timer;
37914f21f67SBibo Mao     uint32_t  phy_id;
380fda3f15bSXiaojuan Yang 
381fda3f15bSXiaojuan Yang     /* 'compatible' string for this CPU for Linux device trees */
382fda3f15bSXiaojuan Yang     const char *dtb_compatible;
383228021f0SSong Gao };
384228021f0SSong Gao 
385228021f0SSong Gao /**
386228021f0SSong Gao  * LoongArchCPUClass:
387228021f0SSong Gao  * @parent_realize: The parent class' realize handler.
388f78b49aeSPeter Maydell  * @parent_phases: The parent class' reset phase handlers.
389228021f0SSong Gao  *
390228021f0SSong Gao  * A LoongArch CPU model.
391228021f0SSong Gao  */
392228021f0SSong Gao struct LoongArchCPUClass {
393228021f0SSong Gao     CPUClass parent_class;
394228021f0SSong Gao 
395228021f0SSong Gao     DeviceRealize parent_realize;
396f78b49aeSPeter Maydell     ResettablePhases parent_phases;
397228021f0SSong Gao };
398228021f0SSong Gao 
3997e1c521eSXiaojuan Yang /*
4007e1c521eSXiaojuan Yang  * LoongArch CPUs has 4 privilege levels.
4017e1c521eSXiaojuan Yang  * 0 for kernel mode, 3 for user mode.
4027e1c521eSXiaojuan Yang  * Define an extra index for DA(direct addressing) mode.
4037e1c521eSXiaojuan Yang  */
404c8885b88SRui Wang #define MMU_PLV_KERNEL   0
405c8885b88SRui Wang #define MMU_PLV_USER     3
406c8885b88SRui Wang #define MMU_IDX_KERNEL   MMU_PLV_KERNEL
407c8885b88SRui Wang #define MMU_IDX_USER     MMU_PLV_USER
408c8885b88SRui Wang #define MMU_IDX_DA       4
4097e1c521eSXiaojuan Yang 
4107e1c521eSXiaojuan Yang static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
4117e1c521eSXiaojuan Yang {
4120093b9a5SSong Gao #ifdef CONFIG_USER_ONLY
413c8885b88SRui Wang     return MMU_IDX_USER;
4140093b9a5SSong Gao #else
415c8885b88SRui Wang     if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) {
4167e1c521eSXiaojuan Yang         return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
417c8885b88SRui Wang     }
418c8885b88SRui Wang     return MMU_IDX_DA;
4190093b9a5SSong Gao #endif
4207e1c521eSXiaojuan Yang }
4217e1c521eSXiaojuan Yang 
42219f82a4aSJiajie Chen static inline bool is_la64(CPULoongArchState *env)
42319f82a4aSJiajie Chen {
42419f82a4aSJiajie Chen     return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64;
42519f82a4aSJiajie Chen }
42619f82a4aSJiajie Chen 
42739665820SJiajie Chen static inline bool is_va32(CPULoongArchState *env)
42839665820SJiajie Chen {
42939665820SJiajie Chen     /* VA32 if !LA64 or VA32L[1-3] */
43039665820SJiajie Chen     bool va32 = !is_la64(env);
43139665820SJiajie Chen     uint64_t plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
43239665820SJiajie Chen     if (plv >= 1 && (FIELD_EX64(env->CSR_MISC, CSR_MISC, VA32) & (1 << plv))) {
43339665820SJiajie Chen         va32 = true;
43439665820SJiajie Chen     }
43539665820SJiajie Chen     return va32;
43639665820SJiajie Chen }
43739665820SJiajie Chen 
4382f6478ffSJiajie Chen static inline void set_pc(CPULoongArchState *env, uint64_t value)
4392f6478ffSJiajie Chen {
4407033c0e6SJiajie Chen     if (is_va32(env)) {
4417033c0e6SJiajie Chen         env->pc = (uint32_t)value;
4427033c0e6SJiajie Chen     } else {
4432f6478ffSJiajie Chen         env->pc = value;
4442f6478ffSJiajie Chen     }
4457033c0e6SJiajie Chen }
4462f6478ffSJiajie Chen 
447b4bda200SRui Wang /*
448b4bda200SRui Wang  * LoongArch CPUs hardware flags.
449b4bda200SRui Wang  */
450b4bda200SRui Wang #define HW_FLAGS_PLV_MASK   R_CSR_CRMD_PLV_MASK  /* 0x03 */
4512419978cSRui Wang #define HW_FLAGS_EUEN_FPE   0x04
452a3f3db5cSSong Gao #define HW_FLAGS_EUEN_SXE   0x08
45332f4916cSJiajie Chen #define HW_FLAGS_CRMD_PG    R_CSR_CRMD_PG_MASK   /* 0x10 */
45439665820SJiajie Chen #define HW_FLAGS_VA32       0x20
45532f4916cSJiajie Chen #define HW_FLAGS_EUEN_ASXE  0x40
456b4bda200SRui Wang 
457bb5de525SAnton Johansson static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
458bb5de525SAnton Johansson                                         uint64_t *cs_base, uint32_t *flags)
4597e1c521eSXiaojuan Yang {
4607e1c521eSXiaojuan Yang     *pc = env->pc;
4617e1c521eSXiaojuan Yang     *cs_base = 0;
462b4bda200SRui Wang     *flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
4632419978cSRui Wang     *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
464a3f3db5cSSong Gao     *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
465b8f1bdf3SSong Gao     *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE;
46639665820SJiajie Chen     *flags |= is_va32(env) * HW_FLAGS_VA32;
4677e1c521eSXiaojuan Yang }
4687e1c521eSXiaojuan Yang 
469228021f0SSong Gao void loongarch_cpu_list(void);
470228021f0SSong Gao 
471228021f0SSong Gao #define cpu_list loongarch_cpu_list
472228021f0SSong Gao 
473228021f0SSong Gao #include "exec/cpu-all.h"
474228021f0SSong Gao 
475228021f0SSong Gao #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
476228021f0SSong Gao 
477464136ceSSong Gao void loongarch_cpu_post_init(Object *obj);
478464136ceSSong Gao 
479228021f0SSong Gao #endif /* LOONGARCH_CPU_H */
480