]> git.proxmox.com Git - mirror_qemu.git/blame - target/hppa/cpu.h
target/hppa: Handle absolute addresses for pa2.0
[mirror_qemu.git] / target / hppa / cpu.h
CommitLineData
61766fe9
RH
1/*
2 * PA-RISC emulation cpu definitions for qemu.
3 *
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
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
d6ea4236 9 * version 2.1 of the License, or (at your option) any later version.
61766fe9
RH
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 HPPA_CPU_H
21#define HPPA_CPU_H
22
61766fe9 23#include "cpu-qom.h"
74433bf0 24#include "exec/cpu-defs.h"
69242e7e 25#include "qemu/cpu-float.h"
66866cc7 26#include "qemu/interval-tree.h"
61766fe9 27
7b93dab5
RH
28/* PA-RISC 1.x processors have a strong memory model. */
29/* ??? While we do not yet implement PA-RISC 2.0, those processors have
30 a weak memory model, but with TLB bits that force ordering on a per-page
31 basis. It's probably easier to fall back to a strong memory model. */
32#define TCG_GUEST_DEFAULT_MO TCG_MO_ALL
33
bb67ec32
RH
34#define MMU_KERNEL_IDX 7
35#define MMU_KERNEL_P_IDX 8
36#define MMU_PL1_IDX 9
37#define MMU_PL1_P_IDX 10
38#define MMU_PL2_IDX 11
39#define MMU_PL2_P_IDX 12
40#define MMU_USER_IDX 13
41#define MMU_USER_P_IDX 14
42#define MMU_PHYS_IDX 15
43
44#define MMU_IDX_TO_PRIV(MIDX) (((MIDX) - MMU_KERNEL_IDX) / 2)
45#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
46#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
c01e5dfb 47
61766fe9
RH
48#define TARGET_INSN_START_EXTRA_WORDS 1
49
88b7ad10
HD
50/* No need to flush MMU_PHYS_IDX */
51#define HPPA_MMU_FLUSH_MASK \
bb67ec32
RH
52 (1 << MMU_KERNEL_IDX | 1 << MMU_KERNEL_P_IDX | \
53 1 << MMU_PL1_IDX | 1 << MMU_PL1_P_IDX | \
54 1 << MMU_PL2_IDX | 1 << MMU_PL2_P_IDX | \
55 1 << MMU_USER_IDX | 1 << MMU_USER_P_IDX)
56
57/* Indicies to flush for access_id changes. */
58#define HPPA_MMU_FLUSH_P_MASK \
59 (1 << MMU_KERNEL_P_IDX | 1 << MMU_PL1_P_IDX | \
60 1 << MMU_PL2_P_IDX | 1 << MMU_USER_P_IDX)
88b7ad10 61
8b81968c 62/* Hardware exceptions, interrupts, faults, and traps. */
2986721d
RH
63#define EXCP_HPMC 1 /* high priority machine check */
64#define EXCP_POWER_FAIL 2
65#define EXCP_RC 3 /* recovery counter */
66#define EXCP_EXT_INTERRUPT 4 /* external interrupt */
67#define EXCP_LPMC 5 /* low priority machine check */
68#define EXCP_ITLB_MISS 6 /* itlb miss / instruction page fault */
69#define EXCP_IMP 7 /* instruction memory protection trap */
70#define EXCP_ILL 8 /* illegal instruction trap */
71#define EXCP_BREAK 9 /* break instruction */
72#define EXCP_PRIV_OPR 10 /* privileged operation trap */
73#define EXCP_PRIV_REG 11 /* privileged register trap */
74#define EXCP_OVERFLOW 12 /* signed overflow trap */
75#define EXCP_COND 13 /* trap-on-condition */
76#define EXCP_ASSIST 14 /* assist exception trap */
77#define EXCP_DTLB_MISS 15 /* dtlb miss / data page fault */
78#define EXCP_NA_ITLB_MISS 16 /* non-access itlb miss */
79#define EXCP_NA_DTLB_MISS 17 /* non-access dtlb miss */
80#define EXCP_DMP 18 /* data memory protection trap */
81#define EXCP_DMB 19 /* data memory break trap */
82#define EXCP_TLB_DIRTY 20 /* tlb dirty bit trap */
83#define EXCP_PAGE_REF 21 /* page reference trap */
84#define EXCP_ASSIST_EMU 22 /* assist emulation trap */
85#define EXCP_HPT 23 /* high-privilege transfer trap */
86#define EXCP_LPT 24 /* low-privilege transfer trap */
87#define EXCP_TB 25 /* taken branch trap */
88#define EXCP_DMAR 26 /* data memory access rights trap */
89#define EXCP_DMPI 27 /* data memory protection id trap */
90#define EXCP_UNALIGN 28 /* unaligned data reference trap */
91#define EXCP_PER_INTERRUPT 29 /* performance monitor interrupt */
92
93/* Exceptions for linux-user emulation. */
94#define EXCP_SYSCALL 30
95#define EXCP_SYSCALL_LWS 31
61766fe9 96
4a4554c6
HD
97/* Emulated hardware TOC button */
98#define EXCP_TOC 32 /* TOC = Transfer of control (NMI) */
99
100#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 /* TOC */
101
fa57e327
RH
102/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
103#define PSW_I 0x00000001
104#define PSW_D 0x00000002
105#define PSW_P 0x00000004
106#define PSW_Q 0x00000008
107#define PSW_R 0x00000010
108#define PSW_F 0x00000020
109#define PSW_G 0x00000040 /* PA1.x only */
110#define PSW_O 0x00000080 /* PA2.0 only */
111#define PSW_CB 0x0000ff00
112#define PSW_M 0x00010000
113#define PSW_V 0x00020000
114#define PSW_C 0x00040000
115#define PSW_B 0x00080000
116#define PSW_X 0x00100000
117#define PSW_N 0x00200000
118#define PSW_L 0x00400000
119#define PSW_H 0x00800000
120#define PSW_T 0x01000000
121#define PSW_S 0x02000000
122#define PSW_E 0x04000000
123#ifdef TARGET_HPPA64
124#define PSW_W 0x08000000 /* PA2.0 only */
125#else
126#define PSW_W 0
127#endif
128#define PSW_Z 0x40000000 /* PA1.x only */
129#define PSW_Y 0x80000000 /* PA1.x only */
130
131#define PSW_SM (PSW_W | PSW_E | PSW_O | PSW_G | PSW_F \
132 | PSW_R | PSW_Q | PSW_P | PSW_D | PSW_I)
133
134/* ssm/rsm instructions number PSW_W and PSW_E differently */
135#define PSW_SM_I PSW_I /* Enable External Interrupts */
136#define PSW_SM_D PSW_D
137#define PSW_SM_P PSW_P
138#define PSW_SM_Q PSW_Q /* Enable Interrupt State Collection */
139#define PSW_SM_R PSW_R /* Enable Recover Counter Trap */
140#ifdef TARGET_HPPA64
141#define PSW_SM_E 0x100
142#define PSW_SM_W 0x200 /* PA2.0 only : Enable Wide Mode */
143#else
144#define PSW_SM_E 0
145#define PSW_SM_W 0
146#endif
147
35136a77 148#define CR_RC 0
d5de20bd
SS
149#define CR_PID1 8
150#define CR_PID2 9
151#define CR_PID3 12
152#define CR_PID4 13
35136a77
RH
153#define CR_SCRCCR 10
154#define CR_SAR 11
155#define CR_IVA 14
156#define CR_EIEM 15
157#define CR_IT 16
158#define CR_IIASQ 17
159#define CR_IIAOQ 18
160#define CR_IIR 19
161#define CR_ISR 20
162#define CR_IOR 21
163#define CR_IPSW 22
164#define CR_EIRR 23
165
eaa3783b
RH
166#if TARGET_REGISTER_BITS == 32
167typedef uint32_t target_ureg;
168typedef int32_t target_sreg;
169#define TREG_FMT_lx "%08"PRIx32
170#define TREG_FMT_ld "%"PRId32
171#else
172typedef uint64_t target_ureg;
173typedef int64_t target_sreg;
174#define TREG_FMT_lx "%016"PRIx64
175#define TREG_FMT_ld "%"PRId64
176#endif
177
729cd350 178typedef struct HPPATLBEntry {
d7553f35
RH
179 union {
180 IntervalTreeNode itree;
181 struct HPPATLBEntry *unused_next;
182 };
66866cc7 183
650cdb2a 184 target_ureg pa;
f8cda28b
RH
185
186 unsigned entry_valid : 1;
187
650cdb2a
RH
188 unsigned u : 1;
189 unsigned t : 1;
190 unsigned d : 1;
191 unsigned b : 1;
650cdb2a
RH
192 unsigned ar_type : 3;
193 unsigned ar_pl1 : 2;
194 unsigned ar_pl2 : 2;
650cdb2a 195 unsigned access_id : 16;
729cd350 196} HPPATLBEntry;
650cdb2a 197
1ea4a06a 198typedef struct CPUArchState {
f8c0fd98
HD
199 target_ureg iaoq_f; /* front */
200 target_ureg iaoq_b; /* back, aka next instruction */
201
eaa3783b 202 target_ureg gr[32];
61766fe9 203 uint64_t fr[32];
33423472 204 uint64_t sr[8]; /* stored shifted into place for gva */
61766fe9 205
eaa3783b
RH
206 target_ureg psw; /* All psw bits except the following: */
207 target_ureg psw_n; /* boolean */
208 target_sreg psw_v; /* in most significant bit */
61766fe9
RH
209
210 /* Splitting the carry-borrow field into the MSB and "the rest", allows
211 * for "the rest" to be deleted when it is unused, but the MSB is in use.
212 * In addition, it's easier to compute carry-in for bit B+1 than it is to
213 * compute carry-out for bit B (3 vs 4 insns for addition, assuming the
214 * host has the appropriate add-with-carry insn to compute the msb).
215 * Therefore the carry bits are stored as: cb_msb : cb & 0x11111110.
216 */
eaa3783b
RH
217 target_ureg psw_cb; /* in least significant bit of next nibble */
218 target_ureg psw_cb_msb; /* boolean */
61766fe9 219
c301f34e
RH
220 uint64_t iasq_f;
221 uint64_t iasq_b;
61766fe9 222
61766fe9
RH
223 uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */
224 float_status fp_status;
225
35136a77
RH
226 target_ureg cr[32]; /* control registers */
227 target_ureg cr_back[2]; /* back of cr17/cr18 */
f49b3537 228 target_ureg shadow[7]; /* shadow registers */
35136a77 229
9cf2112b
RH
230 /*
231 * ??? The number of entries isn't specified by the architecture.
232 * BTLBs are not supported in 64-bit machines.
233 */
234#define PA10_BTLB_FIXED 16
235#define PA10_BTLB_VARIABLE 0
df5c6a50 236#define HPPA_TLB_ENTRIES 256
df5c6a50 237
d7553f35 238 /* Index for round-robin tlb eviction. */
650cdb2a 239 uint32_t tlb_last;
d7553f35
RH
240
241 /*
242 * For pa1.x, the partial initialized, still invalid tlb entry
243 * which has had ITLBA performed, but not yet ITLBP.
244 */
245 HPPATLBEntry *tlb_partial;
246
247 /* Linked list of all invalid (unused) tlb entries. */
248 HPPATLBEntry *tlb_unused;
249
250 /* Root of the search tree for all valid tlb entries. */
251 IntervalTreeRoot tlb_root;
252
253 HPPATLBEntry tlb[HPPA_TLB_ENTRIES];
1ea4a06a 254} CPUHPPAState;
61766fe9
RH
255
256/**
257 * HPPACPU:
258 * @env: #CPUHPPAState
259 *
260 * An HPPA CPU.
261 */
b36e239e 262struct ArchCPU {
61766fe9
RH
263 /*< private >*/
264 CPUState parent_obj;
265 /*< public >*/
266
267 CPUHPPAState env;
49c29d6c 268 QEMUTimer *alarm_timer;
61766fe9
RH
269};
270
61766fe9
RH
271#include "exec/cpu-all.h"
272
bd6243a3
RH
273static inline bool hppa_is_pa20(CPUHPPAState *env)
274{
275 return object_dynamic_cast(OBJECT(env_cpu(env)), TYPE_HPPA64_CPU) != NULL;
276}
277
9cf2112b
RH
278static inline int HPPA_BTLB_ENTRIES(CPUHPPAState *env)
279{
280 return hppa_is_pa20(env) ? 0 : PA10_BTLB_FIXED + PA10_BTLB_VARIABLE;
281}
282
61766fe9
RH
283static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch)
284{
3d68ee7b
RH
285#ifdef CONFIG_USER_ONLY
286 return MMU_USER_IDX;
287#else
288 if (env->psw & (ifetch ? PSW_C : PSW_D)) {
bb67ec32 289 return PRIV_P_TO_MMU_IDX(env->iaoq_f & 3, env->psw & PSW_P);
3d68ee7b
RH
290 }
291 return MMU_PHYS_IDX; /* mmu disabled */
292#endif
61766fe9
RH
293}
294
295void hppa_translate_init(void);
296
0dacec87 297#define CPU_RESOLVING_TYPE TYPE_HPPA_CPU
61766fe9 298
c301f34e
RH
299static inline target_ulong hppa_form_gva_psw(target_ureg psw, uint64_t spc,
300 target_ureg off)
301{
302#ifdef CONFIG_USER_ONLY
303 return off;
304#else
305 off &= (psw & PSW_W ? 0x3fffffffffffffffull : 0xffffffffull);
306 return spc | off;
307#endif
308}
309
310static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc,
311 target_ureg off)
312{
313 return hppa_form_gva_psw(env->psw, spc, off);
314}
315
ccdf741c
RH
316hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr);
317hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
318
217d1a5e
RH
319/*
320 * Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
494737b7
RH
321 * TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the
322 * same value.
323 */
324#define TB_FLAG_SR_SAME PSW_I
c301f34e 325#define TB_FLAG_PRIV_SHIFT 8
217d1a5e 326#define TB_FLAG_UNALIGN 0x400
c301f34e 327
bb5de525
AJ
328static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
329 uint64_t *cs_base, uint32_t *pflags)
61766fe9 330{
c301f34e
RH
331 uint32_t flags = env->psw_n * PSW_N;
332
333 /* TB lookup assumes that PC contains the complete virtual address.
334 If we leave space+offset separate, we'll get ITLB misses to an
335 incomplete virtual address. This also means that we must separate
8b81968c 336 out current cpu privilege from the low bits of IAOQ_F. */
c301f34e 337#ifdef CONFIG_USER_ONLY
ebd0e151
RH
338 *pc = env->iaoq_f & -4;
339 *cs_base = env->iaoq_b & -4;
217d1a5e 340 flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
c301f34e 341#else
bb67ec32
RH
342 /* ??? E, T, H, L, B bits need to be here, when implemented. */
343 flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
c301f34e
RH
344 flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
345
346 *pc = (env->psw & PSW_C
347 ? hppa_form_gva_psw(env->psw, env->iasq_f, env->iaoq_f & -4)
348 : env->iaoq_f & -4);
349 *cs_base = env->iasq_f;
350
351 /* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
352 low 32-bits of CS_BASE. This will succeed for all direct branches,
353 which is the primary case we care about -- using goto_tb within a page.
354 Failure is indicated by a zero difference. */
355 if (env->iasq_f == env->iasq_b) {
356 target_sreg diff = env->iaoq_b - env->iaoq_f;
357 if (TARGET_REGISTER_BITS == 32 || diff == (int32_t)diff) {
358 *cs_base |= (uint32_t)diff;
359 }
360 }
494737b7
RH
361 if ((env->sr[4] == env->sr[5])
362 & (env->sr[4] == env->sr[6])
363 & (env->sr[4] == env->sr[7])) {
364 flags |= TB_FLAG_SR_SAME;
365 }
c301f34e
RH
366#endif
367
368 *pflags = flags;
61766fe9
RH
369}
370
eaa3783b
RH
371target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
372void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg);
61766fe9
RH
373void cpu_hppa_loaded_fr0(CPUHPPAState *env);
374
d5de20bd
SS
375#ifdef CONFIG_USER_ONLY
376static inline void cpu_hppa_change_prot_id(CPUHPPAState *env) { }
377#else
378void cpu_hppa_change_prot_id(CPUHPPAState *env);
379#endif
380
a010bdbe 381int hppa_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
61766fe9 382int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
90c84c56 383void hppa_cpu_dump_state(CPUState *cs, FILE *f, int);
860e0b96 384#ifndef CONFIG_USER_ONLY
d7553f35 385void hppa_ptlbe(CPUHPPAState *env);
6d2d454a 386hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
3c7bef03
RH
387bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
388 MMUAccessType access_type, int mmu_idx,
389 bool probe, uintptr_t retaddr);
68fa1780
PMD
390void hppa_cpu_do_interrupt(CPUState *cpu);
391bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
650cdb2a 392int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
fa824d99 393 int type, hwaddr *pphys, int *pprot,
729cd350 394 HPPATLBEntry **tlb_entry);
4f5f2548 395extern const MemoryRegionOps hppa_io_eir_ops;
8a9358cc 396extern const VMStateDescription vmstate_hppa_cpu;
49c29d6c 397void hppa_cpu_alarm_timer(void *);
43e05652 398int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr);
650cdb2a 399#endif
8905770b 400G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);
61766fe9 401
d3ae32d4
RH
402#define CPU_RESOLVING_TYPE TYPE_HPPA_CPU
403
404#define cpu_list hppa_cpu_list
405void hppa_cpu_list(void);
406
61766fe9 407#endif /* HPPA_CPU_H */