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