xref: /openbmc/qemu/target/mips/internal.h (revision 0b84b662)
1 /* mips internal definitions and helpers
2  *
3  * This work is licensed under the terms of the GNU GPL, version 2 or later.
4  * See the COPYING file in the top-level directory.
5  */
6 
7 #ifndef MIPS_INTERNAL_H
8 #define MIPS_INTERNAL_H
9 
10 #include "fpu/softfloat-helpers.h"
11 
12 /* MMU types, the first four entries have the same layout as the
13    CP0C0_MT field.  */
14 enum mips_mmu_types {
15     MMU_TYPE_NONE,
16     MMU_TYPE_R4000,
17     MMU_TYPE_RESERVED,
18     MMU_TYPE_FMT,
19     MMU_TYPE_R3000,
20     MMU_TYPE_R6000,
21     MMU_TYPE_R8000
22 };
23 
24 struct mips_def_t {
25     const char *name;
26     int32_t CP0_PRid;
27     int32_t CP0_Config0;
28     int32_t CP0_Config1;
29     int32_t CP0_Config2;
30     int32_t CP0_Config3;
31     int32_t CP0_Config4;
32     int32_t CP0_Config4_rw_bitmask;
33     int32_t CP0_Config5;
34     int32_t CP0_Config5_rw_bitmask;
35     int32_t CP0_Config6;
36     int32_t CP0_Config7;
37     target_ulong CP0_LLAddr_rw_bitmask;
38     int CP0_LLAddr_shift;
39     int32_t SYNCI_Step;
40     int32_t CCRes;
41     int32_t CP0_Status_rw_bitmask;
42     int32_t CP0_TCStatus_rw_bitmask;
43     int32_t CP0_SRSCtl;
44     int32_t CP1_fcr0;
45     int32_t CP1_fcr31_rw_bitmask;
46     int32_t CP1_fcr31;
47     int32_t MSAIR;
48     int32_t SEGBITS;
49     int32_t PABITS;
50     int32_t CP0_SRSConf0_rw_bitmask;
51     int32_t CP0_SRSConf0;
52     int32_t CP0_SRSConf1_rw_bitmask;
53     int32_t CP0_SRSConf1;
54     int32_t CP0_SRSConf2_rw_bitmask;
55     int32_t CP0_SRSConf2;
56     int32_t CP0_SRSConf3_rw_bitmask;
57     int32_t CP0_SRSConf3;
58     int32_t CP0_SRSConf4_rw_bitmask;
59     int32_t CP0_SRSConf4;
60     int32_t CP0_PageGrain_rw_bitmask;
61     int32_t CP0_PageGrain;
62     target_ulong CP0_EBaseWG_rw_bitmask;
63     uint64_t insn_flags;
64     enum mips_mmu_types mmu_type;
65     int32_t SAARP;
66 };
67 
68 extern const struct mips_def_t mips_defs[];
69 extern const int mips_defs_number;
70 
71 enum CPUMIPSMSADataFormat {
72     DF_BYTE = 0,
73     DF_HALF,
74     DF_WORD,
75     DF_DOUBLE
76 };
77 
78 void mips_cpu_do_interrupt(CPUState *cpu);
79 bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
80 void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
81 hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
82 int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
83 int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
84 void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
85                                   MMUAccessType access_type,
86                                   int mmu_idx, uintptr_t retaddr);
87 
88 #if !defined(CONFIG_USER_ONLY)
89 
90 typedef struct r4k_tlb_t r4k_tlb_t;
91 struct r4k_tlb_t {
92     target_ulong VPN;
93     uint32_t PageMask;
94     uint16_t ASID;
95     unsigned int G:1;
96     unsigned int C0:3;
97     unsigned int C1:3;
98     unsigned int V0:1;
99     unsigned int V1:1;
100     unsigned int D0:1;
101     unsigned int D1:1;
102     unsigned int XI0:1;
103     unsigned int XI1:1;
104     unsigned int RI0:1;
105     unsigned int RI1:1;
106     unsigned int EHINV:1;
107     uint64_t PFN[2];
108 };
109 
110 struct CPUMIPSTLBContext {
111     uint32_t nb_tlb;
112     uint32_t tlb_in_use;
113     int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot,
114                        target_ulong address, int rw, int access_type);
115     void (*helper_tlbwi)(struct CPUMIPSState *env);
116     void (*helper_tlbwr)(struct CPUMIPSState *env);
117     void (*helper_tlbp)(struct CPUMIPSState *env);
118     void (*helper_tlbr)(struct CPUMIPSState *env);
119     void (*helper_tlbinv)(struct CPUMIPSState *env);
120     void (*helper_tlbinvf)(struct CPUMIPSState *env);
121     union {
122         struct {
123             r4k_tlb_t tlb[MIPS_TLB_MAX];
124         } r4k;
125     } mmu;
126 };
127 
128 int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
129                        target_ulong address, int rw, int access_type);
130 int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
131                           target_ulong address, int rw, int access_type);
132 int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
133                     target_ulong address, int rw, int access_type);
134 void r4k_helper_tlbwi(CPUMIPSState *env);
135 void r4k_helper_tlbwr(CPUMIPSState *env);
136 void r4k_helper_tlbp(CPUMIPSState *env);
137 void r4k_helper_tlbr(CPUMIPSState *env);
138 void r4k_helper_tlbinv(CPUMIPSState *env);
139 void r4k_helper_tlbinvf(CPUMIPSState *env);
140 void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
141 
142 void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
143                                     vaddr addr, unsigned size,
144                                     MMUAccessType access_type,
145                                     int mmu_idx, MemTxAttrs attrs,
146                                     MemTxResult response, uintptr_t retaddr);
147 hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
148                                   int rw);
149 #endif
150 
151 #define cpu_signal_handler cpu_mips_signal_handler
152 
153 #ifndef CONFIG_USER_ONLY
154 extern const VMStateDescription vmstate_mips_cpu;
155 #endif
156 
157 static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
158 {
159     return (env->CP0_Status & (1 << CP0St_IE)) &&
160         !(env->CP0_Status & (1 << CP0St_EXL)) &&
161         !(env->CP0_Status & (1 << CP0St_ERL)) &&
162         !(env->hflags & MIPS_HFLAG_DM) &&
163         /* Note that the TCStatus IXMT field is initialized to zero,
164            and only MT capable cores can set it to one. So we don't
165            need to check for MT capabilities here.  */
166         !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
167 }
168 
169 /* Check if there is pending and not masked out interrupt */
170 static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
171 {
172     int32_t pending;
173     int32_t status;
174     bool r;
175 
176     pending = env->CP0_Cause & CP0Ca_IP_mask;
177     status = env->CP0_Status & CP0Ca_IP_mask;
178 
179     if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
180         /* A MIPS configured with a vectorizing external interrupt controller
181            will feed a vector into the Cause pending lines. The core treats
182            the status lines as a vector level, not as indiviual masks.  */
183         r = pending > status;
184     } else {
185         /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
186            treats the pending lines as individual interrupt lines, the status
187            lines are individual masks.  */
188         r = (pending & status) != 0;
189     }
190     return r;
191 }
192 
193 void mips_tcg_init(void);
194 
195 /* TODO QOM'ify CPU reset and remove */
196 void cpu_state_reset(CPUMIPSState *s);
197 void cpu_mips_realize_env(CPUMIPSState *env);
198 
199 /* cp0_timer.c */
200 uint32_t cpu_mips_get_random(CPUMIPSState *env);
201 uint32_t cpu_mips_get_count(CPUMIPSState *env);
202 void cpu_mips_store_count(CPUMIPSState *env, uint32_t value);
203 void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value);
204 void cpu_mips_start_count(CPUMIPSState *env);
205 void cpu_mips_stop_count(CPUMIPSState *env);
206 
207 /* helper.c */
208 bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
209                        MMUAccessType access_type, int mmu_idx,
210                        bool probe, uintptr_t retaddr);
211 
212 /* op_helper.c */
213 uint32_t float_class_s(uint32_t arg, float_status *fst);
214 uint64_t float_class_d(uint64_t arg, float_status *fst);
215 
216 extern unsigned int ieee_rm[];
217 int ieee_ex_to_mips(int xcpt);
218 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
219 
220 static inline void restore_rounding_mode(CPUMIPSState *env)
221 {
222     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
223                             &env->active_fpu.fp_status);
224 }
225 
226 static inline void restore_flush_mode(CPUMIPSState *env)
227 {
228     set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
229                       &env->active_fpu.fp_status);
230 }
231 
232 static inline void restore_snan_bit_mode(CPUMIPSState *env)
233 {
234     set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
235                         &env->active_fpu.fp_status);
236 }
237 
238 static inline void restore_fp_status(CPUMIPSState *env)
239 {
240     restore_rounding_mode(env);
241     restore_flush_mode(env);
242     restore_snan_bit_mode(env);
243 }
244 
245 static inline void restore_msa_fp_status(CPUMIPSState *env)
246 {
247     float_status *status = &env->active_tc.msa_fp_status;
248     int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
249     bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
250 
251     set_float_rounding_mode(ieee_rm[rounding_mode], status);
252     set_flush_to_zero(flush_to_zero, status);
253     set_flush_inputs_to_zero(flush_to_zero, status);
254 }
255 
256 static inline void restore_pamask(CPUMIPSState *env)
257 {
258     if (env->hflags & MIPS_HFLAG_ELPA) {
259         env->PAMask = (1ULL << env->PABITS) - 1;
260     } else {
261         env->PAMask = PAMASK_BASE;
262     }
263 }
264 
265 static inline int mips_vpe_active(CPUMIPSState *env)
266 {
267     int active = 1;
268 
269     /* Check that the VPE is enabled.  */
270     if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
271         active = 0;
272     }
273     /* Check that the VPE is activated.  */
274     if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
275         active = 0;
276     }
277 
278     /* Now verify that there are active thread contexts in the VPE.
279 
280        This assumes the CPU model will internally reschedule threads
281        if the active one goes to sleep. If there are no threads available
282        the active one will be in a sleeping state, and we can turn off
283        the entire VPE.  */
284     if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) {
285         /* TC is not activated.  */
286         active = 0;
287     }
288     if (env->active_tc.CP0_TCHalt & 1) {
289         /* TC is in halt state.  */
290         active = 0;
291     }
292 
293     return active;
294 }
295 
296 static inline int mips_vp_active(CPUMIPSState *env)
297 {
298     CPUState *other_cs = first_cpu;
299 
300     /* Check if the VP disabled other VPs (which means the VP is enabled) */
301     if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
302         return 1;
303     }
304 
305     /* Check if the virtual processor is disabled due to a DVP */
306     CPU_FOREACH(other_cs) {
307         MIPSCPU *other_cpu = MIPS_CPU(other_cs);
308         if ((&other_cpu->env != env) &&
309             ((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
310             return 0;
311         }
312     }
313     return 1;
314 }
315 
316 static inline void compute_hflags(CPUMIPSState *env)
317 {
318     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
319                      MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
320                      MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
321                      MIPS_HFLAG_DSP_R3 | MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA |
322                      MIPS_HFLAG_FRE | MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
323     if (env->CP0_Status & (1 << CP0St_ERL)) {
324         env->hflags |= MIPS_HFLAG_ERL;
325     }
326     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
327         !(env->CP0_Status & (1 << CP0St_ERL)) &&
328         !(env->hflags & MIPS_HFLAG_DM)) {
329         env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
330     }
331 #if defined(TARGET_MIPS64)
332     if ((env->insn_flags & ISA_MIPS3) &&
333         (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
334          (env->CP0_Status & (1 << CP0St_PX)) ||
335          (env->CP0_Status & (1 << CP0St_UX)))) {
336         env->hflags |= MIPS_HFLAG_64;
337     }
338 
339     if (!(env->insn_flags & ISA_MIPS3)) {
340         env->hflags |= MIPS_HFLAG_AWRAP;
341     } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
342                !(env->CP0_Status & (1 << CP0St_UX))) {
343         env->hflags |= MIPS_HFLAG_AWRAP;
344     } else if (env->insn_flags & ISA_MIPS64R6) {
345         /* Address wrapping for Supervisor and Kernel is specified in R6 */
346         if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
347              !(env->CP0_Status & (1 << CP0St_SX))) ||
348             (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
349              !(env->CP0_Status & (1 << CP0St_KX)))) {
350             env->hflags |= MIPS_HFLAG_AWRAP;
351         }
352     }
353 #endif
354     if (((env->CP0_Status & (1 << CP0St_CU0)) &&
355          !(env->insn_flags & ISA_MIPS32R6)) ||
356         !(env->hflags & MIPS_HFLAG_KSU)) {
357         env->hflags |= MIPS_HFLAG_CP0;
358     }
359     if (env->CP0_Status & (1 << CP0St_CU1)) {
360         env->hflags |= MIPS_HFLAG_FPU;
361     }
362     if (env->CP0_Status & (1 << CP0St_FR)) {
363         env->hflags |= MIPS_HFLAG_F64;
364     }
365     if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
366         (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
367         env->hflags |= MIPS_HFLAG_SBRI;
368     }
369     if (env->insn_flags & ASE_DSP_R3) {
370         /*
371          * Our cpu supports DSP R3 ASE, so enable
372          * access to DSP R3 resources.
373          */
374         if (env->CP0_Status & (1 << CP0St_MX)) {
375             env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
376                            MIPS_HFLAG_DSP_R3;
377         }
378     } else if (env->insn_flags & ASE_DSP_R2) {
379         /*
380          * Our cpu supports DSP R2 ASE, so enable
381          * access to DSP R2 resources.
382          */
383         if (env->CP0_Status & (1 << CP0St_MX)) {
384             env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2;
385         }
386 
387     } else if (env->insn_flags & ASE_DSP) {
388         /*
389          * Our cpu supports DSP ASE, so enable
390          * access to DSP resources.
391          */
392         if (env->CP0_Status & (1 << CP0St_MX)) {
393             env->hflags |= MIPS_HFLAG_DSP;
394         }
395 
396     }
397     if (env->insn_flags & ISA_MIPS32R2) {
398         if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
399             env->hflags |= MIPS_HFLAG_COP1X;
400         }
401     } else if (env->insn_flags & ISA_MIPS32) {
402         if (env->hflags & MIPS_HFLAG_64) {
403             env->hflags |= MIPS_HFLAG_COP1X;
404         }
405     } else if (env->insn_flags & ISA_MIPS4) {
406         /* All supported MIPS IV CPUs use the XX (CU3) to enable
407            and disable the MIPS IV extensions to the MIPS III ISA.
408            Some other MIPS IV CPUs ignore the bit, so the check here
409            would be too restrictive for them.  */
410         if (env->CP0_Status & (1U << CP0St_CU3)) {
411             env->hflags |= MIPS_HFLAG_COP1X;
412         }
413     }
414     if (env->insn_flags & ASE_MSA) {
415         if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
416             env->hflags |= MIPS_HFLAG_MSA;
417         }
418     }
419     if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
420         if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
421             env->hflags |= MIPS_HFLAG_FRE;
422         }
423     }
424     if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
425         if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
426             env->hflags |= MIPS_HFLAG_ELPA;
427         }
428     }
429 }
430 
431 void cpu_mips_tlb_flush(CPUMIPSState *env);
432 void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
433 void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
434 void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
435 
436 void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
437                                           int error_code, uintptr_t pc);
438 
439 static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
440                                                     uint32_t exception,
441                                                     uintptr_t pc)
442 {
443     do_raise_exception_err(env, exception, 0, pc);
444 }
445 
446 #endif
447