xref: /openbmc/qemu/target/alpha/cpu.h (revision a9ded601)
1 /*
2  *  Alpha emulation cpu definitions for qemu.
3  *
4  *  Copyright (c) 2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ALPHA_CPU_H
21 #define ALPHA_CPU_H
22 
23 #include "qemu-common.h"
24 #include "cpu-qom.h"
25 
26 #define TARGET_LONG_BITS 64
27 #define ALIGNED_ONLY
28 
29 #define CPUArchState struct CPUAlphaState
30 
31 /* Alpha processors have a weak memory model */
32 #define TCG_GUEST_DEFAULT_MO      (0)
33 
34 #include "exec/cpu-defs.h"
35 
36 #include "fpu/softfloat.h"
37 
38 #define ICACHE_LINE_SIZE 32
39 #define DCACHE_LINE_SIZE 32
40 
41 #define TARGET_PAGE_BITS 13
42 
43 #ifdef CONFIG_USER_ONLY
44 /* ??? The kernel likes to give addresses in high memory.  If the host has
45    more virtual address space than the guest, this can lead to impossible
46    allocations.  Honor the long-standing assumption that only kernel addrs
47    are negative, but otherwise allow allocations anywhere.  This could lead
48    to tricky emulation problems for programs doing tagged addressing, but
49    that's far fewer than encounter the impossible allocation problem.  */
50 #define TARGET_PHYS_ADDR_SPACE_BITS  63
51 #define TARGET_VIRT_ADDR_SPACE_BITS  63
52 #else
53 /* ??? EV4 has 34 phys addr bits, EV5 has 40, EV6 has 44.  */
54 #define TARGET_PHYS_ADDR_SPACE_BITS  44
55 #define TARGET_VIRT_ADDR_SPACE_BITS  (30 + TARGET_PAGE_BITS)
56 #endif
57 
58 /* Alpha major type */
59 enum {
60     ALPHA_EV3  = 1,
61     ALPHA_EV4  = 2,
62     ALPHA_SIM  = 3,
63     ALPHA_LCA  = 4,
64     ALPHA_EV5  = 5, /* 21164 */
65     ALPHA_EV45 = 6, /* 21064A */
66     ALPHA_EV56 = 7, /* 21164A */
67 };
68 
69 /* EV4 minor type */
70 enum {
71     ALPHA_EV4_2 = 0,
72     ALPHA_EV4_3 = 1,
73 };
74 
75 /* LCA minor type */
76 enum {
77     ALPHA_LCA_1 = 1, /* 21066 */
78     ALPHA_LCA_2 = 2, /* 20166 */
79     ALPHA_LCA_3 = 3, /* 21068 */
80     ALPHA_LCA_4 = 4, /* 21068 */
81     ALPHA_LCA_5 = 5, /* 21066A */
82     ALPHA_LCA_6 = 6, /* 21068A */
83 };
84 
85 /* EV5 minor type */
86 enum {
87     ALPHA_EV5_1 = 1, /* Rev BA, CA */
88     ALPHA_EV5_2 = 2, /* Rev DA, EA */
89     ALPHA_EV5_3 = 3, /* Pass 3 */
90     ALPHA_EV5_4 = 4, /* Pass 3.2 */
91     ALPHA_EV5_5 = 5, /* Pass 4 */
92 };
93 
94 /* EV45 minor type */
95 enum {
96     ALPHA_EV45_1 = 1, /* Pass 1 */
97     ALPHA_EV45_2 = 2, /* Pass 1.1 */
98     ALPHA_EV45_3 = 3, /* Pass 2 */
99 };
100 
101 /* EV56 minor type */
102 enum {
103     ALPHA_EV56_1 = 1, /* Pass 1 */
104     ALPHA_EV56_2 = 2, /* Pass 2 */
105 };
106 
107 enum {
108     IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */
109     IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */
110     IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */
111     IMPLVER_21364 = 3, /* EV7 & EV79 */
112 };
113 
114 enum {
115     AMASK_BWX      = 0x00000001,
116     AMASK_FIX      = 0x00000002,
117     AMASK_CIX      = 0x00000004,
118     AMASK_MVI      = 0x00000100,
119     AMASK_TRAP     = 0x00000200,
120     AMASK_PREFETCH = 0x00001000,
121 };
122 
123 enum {
124     VAX_ROUND_NORMAL = 0,
125     VAX_ROUND_CHOPPED,
126 };
127 
128 enum {
129     IEEE_ROUND_NORMAL = 0,
130     IEEE_ROUND_DYNAMIC,
131     IEEE_ROUND_PLUS,
132     IEEE_ROUND_MINUS,
133     IEEE_ROUND_CHOPPED,
134 };
135 
136 /* IEEE floating-point operations encoding */
137 /* Trap mode */
138 enum {
139     FP_TRAP_I   = 0x0,
140     FP_TRAP_U   = 0x1,
141     FP_TRAP_S  = 0x4,
142     FP_TRAP_SU  = 0x5,
143     FP_TRAP_SUI = 0x7,
144 };
145 
146 /* Rounding mode */
147 enum {
148     FP_ROUND_CHOPPED = 0x0,
149     FP_ROUND_MINUS   = 0x1,
150     FP_ROUND_NORMAL  = 0x2,
151     FP_ROUND_DYNAMIC = 0x3,
152 };
153 
154 /* FPCR bits -- right-shifted 32 so we can use a uint32_t.  */
155 #define FPCR_SUM                (1U << (63 - 32))
156 #define FPCR_INED               (1U << (62 - 32))
157 #define FPCR_UNFD               (1U << (61 - 32))
158 #define FPCR_UNDZ               (1U << (60 - 32))
159 #define FPCR_DYN_SHIFT          (58 - 32)
160 #define FPCR_DYN_CHOPPED        (0U << FPCR_DYN_SHIFT)
161 #define FPCR_DYN_MINUS          (1U << FPCR_DYN_SHIFT)
162 #define FPCR_DYN_NORMAL         (2U << FPCR_DYN_SHIFT)
163 #define FPCR_DYN_PLUS           (3U << FPCR_DYN_SHIFT)
164 #define FPCR_DYN_MASK           (3U << FPCR_DYN_SHIFT)
165 #define FPCR_IOV                (1U << (57 - 32))
166 #define FPCR_INE                (1U << (56 - 32))
167 #define FPCR_UNF                (1U << (55 - 32))
168 #define FPCR_OVF                (1U << (54 - 32))
169 #define FPCR_DZE                (1U << (53 - 32))
170 #define FPCR_INV                (1U << (52 - 32))
171 #define FPCR_OVFD               (1U << (51 - 32))
172 #define FPCR_DZED               (1U << (50 - 32))
173 #define FPCR_INVD               (1U << (49 - 32))
174 #define FPCR_DNZ                (1U << (48 - 32))
175 #define FPCR_DNOD               (1U << (47 - 32))
176 #define FPCR_STATUS_MASK        (FPCR_IOV | FPCR_INE | FPCR_UNF \
177                                  | FPCR_OVF | FPCR_DZE | FPCR_INV)
178 
179 /* The silly software trap enables implemented by the kernel emulation.
180    These are more or less architecturally required, since the real hardware
181    has read-as-zero bits in the FPCR when the features aren't implemented.
182    For the purposes of QEMU, we pretend the FPCR can hold everything.  */
183 #define SWCR_TRAP_ENABLE_INV    (1U << 1)
184 #define SWCR_TRAP_ENABLE_DZE    (1U << 2)
185 #define SWCR_TRAP_ENABLE_OVF    (1U << 3)
186 #define SWCR_TRAP_ENABLE_UNF    (1U << 4)
187 #define SWCR_TRAP_ENABLE_INE    (1U << 5)
188 #define SWCR_TRAP_ENABLE_DNO    (1U << 6)
189 #define SWCR_TRAP_ENABLE_MASK   ((1U << 7) - (1U << 1))
190 
191 #define SWCR_MAP_DMZ            (1U << 12)
192 #define SWCR_MAP_UMZ            (1U << 13)
193 #define SWCR_MAP_MASK           (SWCR_MAP_DMZ | SWCR_MAP_UMZ)
194 
195 #define SWCR_STATUS_INV         (1U << 17)
196 #define SWCR_STATUS_DZE         (1U << 18)
197 #define SWCR_STATUS_OVF         (1U << 19)
198 #define SWCR_STATUS_UNF         (1U << 20)
199 #define SWCR_STATUS_INE         (1U << 21)
200 #define SWCR_STATUS_DNO         (1U << 22)
201 #define SWCR_STATUS_MASK        ((1U << 23) - (1U << 17))
202 
203 #define SWCR_MASK  (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
204 
205 /* MMU modes definitions */
206 
207 /* Alpha has 5 MMU modes: PALcode, Kernel, Executive, Supervisor, and User.
208    The Unix PALcode only exposes the kernel and user modes; presumably
209    executive and supervisor are used by VMS.
210 
211    PALcode itself uses physical mode for code and kernel mode for data;
212    there are PALmode instructions that can access data via physical mode
213    or via an os-installed "alternate mode", which is one of the 4 above.
214 
215    That said, we're only emulating Unix PALcode, and not attempting VMS,
216    so we don't need to implement Executive and Supervisor.  QEMU's own
217    PALcode cheats and usees the KSEG mapping for its code+data rather than
218    physical addresses.  */
219 
220 #define NB_MMU_MODES 3
221 
222 #define MMU_MODE0_SUFFIX _kernel
223 #define MMU_MODE1_SUFFIX _user
224 #define MMU_KERNEL_IDX   0
225 #define MMU_USER_IDX     1
226 #define MMU_PHYS_IDX     2
227 
228 typedef struct CPUAlphaState CPUAlphaState;
229 
230 struct CPUAlphaState {
231     uint64_t ir[31];
232     float64 fir[31];
233     uint64_t pc;
234     uint64_t unique;
235     uint64_t lock_addr;
236     uint64_t lock_value;
237 
238     /* The FPCR, and disassembled portions thereof.  */
239     uint32_t fpcr;
240     uint32_t fpcr_exc_enable;
241     float_status fp_status;
242     uint8_t fpcr_dyn_round;
243     uint8_t fpcr_flush_to_zero;
244 
245     /* The Internal Processor Registers.  Some of these we assume always
246        exist for use in user-mode.  */
247     uint8_t ps;
248     uint8_t intr_flag;
249     uint8_t pal_mode;
250     uint8_t fen;
251 
252     uint32_t pcc_ofs;
253 
254     /* These pass data from the exception logic in the translator and
255        helpers to the OS entry point.  This is used for both system
256        emulation and user-mode.  */
257     uint64_t trap_arg0;
258     uint64_t trap_arg1;
259     uint64_t trap_arg2;
260 
261 #if !defined(CONFIG_USER_ONLY)
262     /* The internal data required by our emulation of the Unix PALcode.  */
263     uint64_t exc_addr;
264     uint64_t palbr;
265     uint64_t ptbr;
266     uint64_t vptptr;
267     uint64_t sysval;
268     uint64_t usp;
269     uint64_t shadow[8];
270     uint64_t scratch[24];
271 #endif
272 
273     /* This alarm doesn't exist in real hardware; we wish it did.  */
274     uint64_t alarm_expire;
275 
276     /* Those resources are used only in QEMU core */
277     CPU_COMMON
278 
279     int error_code;
280 
281     uint32_t features;
282     uint32_t amask;
283     int implver;
284 };
285 
286 /**
287  * AlphaCPU:
288  * @env: #CPUAlphaState
289  *
290  * An Alpha CPU.
291  */
292 struct AlphaCPU {
293     /*< private >*/
294     CPUState parent_obj;
295     /*< public >*/
296 
297     CPUAlphaState env;
298 
299     /* This alarm doesn't exist in real hardware; we wish it did.  */
300     QEMUTimer *alarm_timer;
301 };
302 
303 static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
304 {
305     return container_of(env, AlphaCPU, env);
306 }
307 
308 #define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
309 
310 #define ENV_OFFSET offsetof(AlphaCPU, env)
311 
312 #ifndef CONFIG_USER_ONLY
313 extern const struct VMStateDescription vmstate_alpha_cpu;
314 #endif
315 
316 void alpha_cpu_do_interrupt(CPUState *cpu);
317 bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
318 void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
319                           int flags);
320 hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
321 int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
322 int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
323 void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
324                                    MMUAccessType access_type,
325                                    int mmu_idx, uintptr_t retaddr);
326 
327 #define cpu_list alpha_cpu_list
328 #define cpu_signal_handler cpu_alpha_signal_handler
329 
330 #include "exec/cpu-all.h"
331 
332 enum {
333     FEATURE_ASN    = 0x00000001,
334     FEATURE_SPS    = 0x00000002,
335     FEATURE_VIRBND = 0x00000004,
336     FEATURE_TBCHK  = 0x00000008,
337 };
338 
339 enum {
340     EXCP_RESET,
341     EXCP_MCHK,
342     EXCP_SMP_INTERRUPT,
343     EXCP_CLK_INTERRUPT,
344     EXCP_DEV_INTERRUPT,
345     EXCP_MMFAULT,
346     EXCP_UNALIGN,
347     EXCP_OPCDEC,
348     EXCP_ARITH,
349     EXCP_FEN,
350     EXCP_CALL_PAL,
351 };
352 
353 /* Alpha-specific interrupt pending bits.  */
354 #define CPU_INTERRUPT_TIMER	CPU_INTERRUPT_TGT_EXT_0
355 #define CPU_INTERRUPT_SMP	CPU_INTERRUPT_TGT_EXT_1
356 #define CPU_INTERRUPT_MCHK	CPU_INTERRUPT_TGT_EXT_2
357 
358 /* OSF/1 Page table bits.  */
359 enum {
360     PTE_VALID = 0x0001,
361     PTE_FOR   = 0x0002,  /* used for page protection (fault on read) */
362     PTE_FOW   = 0x0004,  /* used for page protection (fault on write) */
363     PTE_FOE   = 0x0008,  /* used for page protection (fault on exec) */
364     PTE_ASM   = 0x0010,
365     PTE_KRE   = 0x0100,
366     PTE_URE   = 0x0200,
367     PTE_KWE   = 0x1000,
368     PTE_UWE   = 0x2000
369 };
370 
371 /* Hardware interrupt (entInt) constants.  */
372 enum {
373     INT_K_IP,
374     INT_K_CLK,
375     INT_K_MCHK,
376     INT_K_DEV,
377     INT_K_PERF,
378 };
379 
380 /* Memory management (entMM) constants.  */
381 enum {
382     MM_K_TNV,
383     MM_K_ACV,
384     MM_K_FOR,
385     MM_K_FOE,
386     MM_K_FOW
387 };
388 
389 /* Arithmetic exception (entArith) constants.  */
390 enum {
391     EXC_M_SWC = 1,      /* Software completion */
392     EXC_M_INV = 2,      /* Invalid operation */
393     EXC_M_DZE = 4,      /* Division by zero */
394     EXC_M_FOV = 8,      /* Overflow */
395     EXC_M_UNF = 16,     /* Underflow */
396     EXC_M_INE = 32,     /* Inexact result */
397     EXC_M_IOV = 64      /* Integer Overflow */
398 };
399 
400 /* Processor status constants.  */
401 enum {
402     /* Low 3 bits are interrupt mask level.  */
403     PS_INT_MASK = 7,
404 
405     /* Bits 4 and 5 are the mmu mode.  The VMS PALcode uses all 4 modes;
406        The Unix PALcode only uses bit 4.  */
407     PS_USER_MODE = 8
408 };
409 
410 static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
411 {
412     if (env->pal_mode) {
413         return MMU_KERNEL_IDX;
414     } else if (env->ps & PS_USER_MODE) {
415         return MMU_USER_IDX;
416     } else {
417         return MMU_KERNEL_IDX;
418     }
419 }
420 
421 enum {
422     IR_V0   = 0,
423     IR_T0   = 1,
424     IR_T1   = 2,
425     IR_T2   = 3,
426     IR_T3   = 4,
427     IR_T4   = 5,
428     IR_T5   = 6,
429     IR_T6   = 7,
430     IR_T7   = 8,
431     IR_S0   = 9,
432     IR_S1   = 10,
433     IR_S2   = 11,
434     IR_S3   = 12,
435     IR_S4   = 13,
436     IR_S5   = 14,
437     IR_S6   = 15,
438     IR_FP   = IR_S6,
439     IR_A0   = 16,
440     IR_A1   = 17,
441     IR_A2   = 18,
442     IR_A3   = 19,
443     IR_A4   = 20,
444     IR_A5   = 21,
445     IR_T8   = 22,
446     IR_T9   = 23,
447     IR_T10  = 24,
448     IR_T11  = 25,
449     IR_RA   = 26,
450     IR_T12  = 27,
451     IR_PV   = IR_T12,
452     IR_AT   = 28,
453     IR_GP   = 29,
454     IR_SP   = 30,
455     IR_ZERO = 31,
456 };
457 
458 void alpha_translate_init(void);
459 
460 AlphaCPU *cpu_alpha_init(const char *cpu_model);
461 
462 #define cpu_init(cpu_model) CPU(cpu_alpha_init(cpu_model))
463 
464 void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf);
465 /* you can call this signal handler from your SIGBUS and SIGSEGV
466    signal handlers to inform the virtual CPU of exceptions. non zero
467    is returned if the signal was handled by the virtual CPU.  */
468 int cpu_alpha_signal_handler(int host_signum, void *pinfo,
469                              void *puc);
470 int alpha_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
471                                int mmu_idx);
472 void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
473 void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
474 
475 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
476 void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
477 uint64_t cpu_alpha_load_gr(CPUAlphaState *env, unsigned reg);
478 void cpu_alpha_store_gr(CPUAlphaState *env, unsigned reg, uint64_t val);
479 #ifndef CONFIG_USER_ONLY
480 QEMU_NORETURN void alpha_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
481                                                bool is_write, bool is_exec,
482                                                int unused, unsigned size);
483 #endif
484 
485 /* Bits in TB->FLAGS that control how translation is processed.  */
486 enum {
487     TB_FLAGS_PAL_MODE = 1,
488     TB_FLAGS_FEN = 2,
489     TB_FLAGS_USER_MODE = 8,
490 
491     TB_FLAGS_AMASK_SHIFT = 4,
492     TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
493     TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
494     TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
495     TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
496     TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
497     TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
498 };
499 
500 static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
501                                         target_ulong *cs_base, uint32_t *pflags)
502 {
503     int flags = 0;
504 
505     *pc = env->pc;
506     *cs_base = 0;
507 
508     if (env->pal_mode) {
509         flags = TB_FLAGS_PAL_MODE;
510     } else {
511         flags = env->ps & PS_USER_MODE;
512     }
513     if (env->fen) {
514         flags |= TB_FLAGS_FEN;
515     }
516     flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
517 
518     *pflags = flags;
519 }
520 
521 #endif /* ALPHA_CPU_H */
522