1 /*-
2  * Copyright (c) 2007 Marcel Moolenaar
3  * Copyright (c) 2000 Doug Rabson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: stable/10/sys/ia64/include/ia64_cpu.h 223170 2011-06-17 04:26:03Z marcel $
28  */
29 
30 #ifndef _MACHINE_IA64_CPU_H_
31 #define _MACHINE_IA64_CPU_H_
32 
33 /*
34  * Local Interrupt ID.
35  */
36 #define	IA64_LID_GET_SAPIC_ID(x)	((u_int)((x) >> 16) & 0xffff)
37 #define	IA64_LID_SET_SAPIC_ID(x)	((u_int)((x) & 0xffff) << 16)
38 
39 /*
40  * Definition of DCR bits.
41  */
42 #define	IA64_DCR_PP		0x0000000000000001
43 #define	IA64_DCR_BE		0x0000000000000002
44 #define	IA64_DCR_LC		0x0000000000000004
45 #define	IA64_DCR_DM		0x0000000000000100
46 #define	IA64_DCR_DP		0x0000000000000200
47 #define	IA64_DCR_DK		0x0000000000000400
48 #define	IA64_DCR_DX		0x0000000000000800
49 #define	IA64_DCR_DR		0x0000000000001000
50 #define	IA64_DCR_DA		0x0000000000002000
51 #define	IA64_DCR_DD		0x0000000000004000
52 
53 #define	IA64_DCR_DEFAULT					\
54     (IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX |	\
55      IA64_DCR_DR | IA64_DCR_DA | IA64_DCR_DD)
56 
57 /*
58  * Definition of PSR and IPSR bits.
59  */
60 #define IA64_PSR_BE		0x0000000000000002
61 #define IA64_PSR_UP		0x0000000000000004
62 #define IA64_PSR_AC		0x0000000000000008
63 #define IA64_PSR_MFL		0x0000000000000010
64 #define IA64_PSR_MFH		0x0000000000000020
65 #define IA64_PSR_IC		0x0000000000002000
66 #define IA64_PSR_I		0x0000000000004000
67 #define IA64_PSR_PK		0x0000000000008000
68 #define IA64_PSR_DT		0x0000000000020000
69 #define IA64_PSR_DFL		0x0000000000040000
70 #define IA64_PSR_DFH		0x0000000000080000
71 #define IA64_PSR_SP		0x0000000000100000
72 #define IA64_PSR_PP		0x0000000000200000
73 #define IA64_PSR_DI		0x0000000000400000
74 #define IA64_PSR_SI		0x0000000000800000
75 #define IA64_PSR_DB		0x0000000001000000
76 #define IA64_PSR_LP		0x0000000002000000
77 #define IA64_PSR_TB		0x0000000004000000
78 #define IA64_PSR_RT		0x0000000008000000
79 #define IA64_PSR_CPL		0x0000000300000000
80 #define IA64_PSR_CPL_KERN	0x0000000000000000
81 #define IA64_PSR_CPL_1		0x0000000100000000
82 #define IA64_PSR_CPL_2		0x0000000200000000
83 #define IA64_PSR_CPL_USER	0x0000000300000000
84 #define IA64_PSR_IS		0x0000000400000000
85 #define IA64_PSR_MC		0x0000000800000000
86 #define IA64_PSR_IT		0x0000001000000000
87 #define IA64_PSR_ID		0x0000002000000000
88 #define IA64_PSR_DA		0x0000004000000000
89 #define IA64_PSR_DD		0x0000008000000000
90 #define IA64_PSR_SS		0x0000010000000000
91 #define IA64_PSR_RI		0x0000060000000000
92 #define IA64_PSR_RI_0		0x0000000000000000
93 #define IA64_PSR_RI_1		0x0000020000000000
94 #define IA64_PSR_RI_2		0x0000040000000000
95 #define IA64_PSR_ED		0x0000080000000000
96 #define IA64_PSR_BN		0x0000100000000000
97 #define IA64_PSR_IA		0x0000200000000000
98 
99 /*
100  * Definition of ISR bits.
101  */
102 #define IA64_ISR_CODE		0x000000000000ffff
103 #define IA64_ISR_VECTOR		0x0000000000ff0000
104 #define IA64_ISR_X		0x0000000100000000
105 #define IA64_ISR_W		0x0000000200000000
106 #define IA64_ISR_R		0x0000000400000000
107 #define IA64_ISR_NA		0x0000000800000000
108 #define IA64_ISR_SP		0x0000001000000000
109 #define IA64_ISR_RS		0x0000002000000000
110 #define IA64_ISR_IR		0x0000004000000000
111 #define IA64_ISR_NI		0x0000008000000000
112 #define IA64_ISR_SO		0x0000010000000000
113 #define IA64_ISR_EI		0x0000060000000000
114 #define IA64_ISR_EI_0		0x0000000000000000
115 #define IA64_ISR_EI_1		0x0000020000000000
116 #define IA64_ISR_EI_2		0x0000040000000000
117 #define IA64_ISR_ED		0x0000080000000000
118 
119 /*
120  * Vector numbers for various ia64 interrupts.
121  */
122 #define IA64_VEC_VHPT			0
123 #define IA64_VEC_ITLB			1
124 #define IA64_VEC_DTLB			2
125 #define IA64_VEC_ALT_ITLB		3
126 #define IA64_VEC_ALT_DTLB		4
127 #define IA64_VEC_NESTED_DTLB		5
128 #define IA64_VEC_IKEY_MISS		6
129 #define IA64_VEC_DKEY_MISS		7
130 #define IA64_VEC_DIRTY_BIT		8
131 #define IA64_VEC_INST_ACCESS		9
132 #define IA64_VEC_DATA_ACCESS		10
133 #define IA64_VEC_BREAK			11
134 #define IA64_VEC_EXT_INTR		12
135 #define IA64_VEC_PAGE_NOT_PRESENT	20
136 #define IA64_VEC_KEY_PERMISSION		21
137 #define IA64_VEC_INST_ACCESS_RIGHTS	22
138 #define IA64_VEC_DATA_ACCESS_RIGHTS	23
139 #define IA64_VEC_GENERAL_EXCEPTION	24
140 #define IA64_VEC_DISABLED_FP		25
141 #define IA64_VEC_NAT_CONSUMPTION	26
142 #define IA64_VEC_SPECULATION		27
143 #define IA64_VEC_DEBUG			29
144 #define IA64_VEC_UNALIGNED_REFERENCE	30
145 #define IA64_VEC_UNSUPP_DATA_REFERENCE	31
146 #define IA64_VEC_FLOATING_POINT_FAULT	32
147 #define IA64_VEC_FLOATING_POINT_TRAP	33
148 #define IA64_VEC_LOWER_PRIVILEGE_TRANSFER 34
149 #define IA64_VEC_TAKEN_BRANCH_TRAP	35
150 #define IA64_VEC_SINGLE_STEP_TRAP	36
151 #define IA64_VEC_IA32_EXCEPTION		45
152 #define IA64_VEC_IA32_INTERCEPT		46
153 #define IA64_VEC_IA32_INTERRUPT		47
154 
155 /*
156  * IA-32 exceptions.
157  */
158 #define IA32_EXCEPTION_DIVIDE		0
159 #define IA32_EXCEPTION_DEBUG		1
160 #define IA32_EXCEPTION_BREAK		3
161 #define IA32_EXCEPTION_OVERFLOW		4
162 #define IA32_EXCEPTION_BOUND		5
163 #define IA32_EXCEPTION_DNA		7
164 #define IA32_EXCEPTION_NOT_PRESENT	11
165 #define IA32_EXCEPTION_STACK_FAULT	12
166 #define IA32_EXCEPTION_GPFAULT		13
167 #define IA32_EXCEPTION_FPERROR		16
168 #define IA32_EXCEPTION_ALIGNMENT_CHECK	17
169 #define IA32_EXCEPTION_STREAMING_SIMD	19
170 
171 #define IA32_INTERCEPT_INSTRUCTION	0
172 #define IA32_INTERCEPT_GATE		1
173 #define IA32_INTERCEPT_SYSTEM_FLAG	2
174 #define IA32_INTERCEPT_LOCK		4
175 
176 #ifndef LOCORE
177 
178 /*
179  * Various special ia64 instructions.
180  */
181 
182 /*
183  * Memory Fence.
184  */
185 static __inline void
ia64_mf(void)186 ia64_mf(void)
187 {
188 	__asm __volatile("mf");
189 }
190 
191 static __inline void
ia64_mf_a(void)192 ia64_mf_a(void)
193 {
194 	__asm __volatile("mf.a");
195 }
196 
197 /*
198  * Flush Cache.
199  */
200 static __inline void
ia64_fc(uint64_t va)201 ia64_fc(uint64_t va)
202 {
203 	__asm __volatile("fc %0" :: "r"(va));
204 }
205 
206 static __inline void
ia64_fc_i(uint64_t va)207 ia64_fc_i(uint64_t va)
208 {
209 	__asm __volatile("fc.i %0" :: "r"(va));
210 }
211 
212 /*
213  * Sync instruction stream.
214  */
215 static __inline void
ia64_sync_i(void)216 ia64_sync_i(void)
217 {
218 	__asm __volatile("sync.i");
219 }
220 
221 /*
222  * Calculate address in VHPT for va.
223  */
224 static __inline uint64_t
ia64_thash(uint64_t va)225 ia64_thash(uint64_t va)
226 {
227 	uint64_t result;
228 	__asm __volatile("thash %0=%1" : "=r" (result) : "r" (va));
229 	return result;
230 }
231 
232 /*
233  * Calculate VHPT tag for va.
234  */
235 static __inline uint64_t
ia64_ttag(uint64_t va)236 ia64_ttag(uint64_t va)
237 {
238 	uint64_t result;
239 	__asm __volatile("ttag %0=%1" : "=r" (result) : "r" (va));
240 	return result;
241 }
242 
243 /*
244  * Convert virtual address to physical.
245  */
246 static __inline uint64_t
ia64_tpa(uint64_t va)247 ia64_tpa(uint64_t va)
248 {
249 	uint64_t result;
250 	__asm __volatile("tpa %0=%1" : "=r" (result) : "r" (va));
251 	return result;
252 }
253 
254 /*
255  * Generate a ptc.e instruction.
256  */
257 static __inline void
ia64_ptc_e(uint64_t v)258 ia64_ptc_e(uint64_t v)
259 {
260 	__asm __volatile("ptc.e %0;; srlz.i;;" :: "r"(v));
261 }
262 
263 /*
264  * Generate a ptc.g instruction.
265  */
266 static __inline void
ia64_ptc_g(uint64_t va,uint64_t log2size)267 ia64_ptc_g(uint64_t va, uint64_t log2size)
268 {
269 	__asm __volatile("ptc.g %0,%1;;" :: "r"(va), "r"(log2size));
270 }
271 
272 /*
273  * Generate a ptc.ga instruction.
274  */
275 static __inline void
ia64_ptc_ga(uint64_t va,uint64_t log2size)276 ia64_ptc_ga(uint64_t va, uint64_t log2size)
277 {
278 	__asm __volatile("ptc.ga %0,%1;;" :: "r"(va), "r"(log2size));
279 }
280 
281 /*
282  * Generate a ptc.l instruction.
283  */
284 static __inline void
ia64_ptc_l(uint64_t va,uint64_t log2size)285 ia64_ptc_l(uint64_t va, uint64_t log2size)
286 {
287 	__asm __volatile("ptc.l %0,%1;; srlz.i;;" :: "r"(va), "r"(log2size));
288 }
289 
290 /*
291  * Invalidate the ALAT on the local processor.
292  */
293 static __inline void
ia64_invala(void)294 ia64_invala(void)
295 {
296 	__asm __volatile("invala;;");
297 }
298 
299 /*
300  * Unordered memory load.
301  */
302 
303 static __inline uint8_t
ia64_ld1(uint8_t * p)304 ia64_ld1(uint8_t *p)
305 {
306 	uint8_t v;
307 
308 	__asm __volatile("ld1 %0=[%1];;" : "=r"(v) : "r"(p));
309 	return (v);
310 }
311 
312 static __inline uint16_t
ia64_ld2(uint16_t * p)313 ia64_ld2(uint16_t *p)
314 {
315 	uint16_t v;
316 
317 	__asm __volatile("ld2 %0=[%1];;" : "=r"(v) : "r"(p));
318 	return (v);
319 }
320 
321 static __inline uint32_t
ia64_ld4(uint32_t * p)322 ia64_ld4(uint32_t *p)
323 {
324 	uint32_t v;
325 
326 	__asm __volatile("ld4 %0=[%1];;" : "=r"(v) : "r"(p));
327 	return (v);
328 }
329 
330 static __inline uint64_t
ia64_ld8(uint64_t * p)331 ia64_ld8(uint64_t *p)
332 {
333 	uint64_t v;
334 
335 	__asm __volatile("ld8 %0=[%1];;" : "=r"(v) : "r"(p));
336 	return (v);
337 }
338 
339 /*
340  * Unordered memory store.
341  */
342 
343 static __inline void
ia64_st1(uint8_t * p,uint8_t v)344 ia64_st1(uint8_t *p, uint8_t v)
345 {
346 	__asm __volatile("st1 [%0]=%1;;" :: "r"(p), "r"(v));
347 }
348 
349 static __inline void
ia64_st2(uint16_t * p,uint16_t v)350 ia64_st2(uint16_t *p, uint16_t v)
351 {
352 	__asm __volatile("st2 [%0]=%1;;" :: "r"(p), "r"(v));
353 }
354 
355 static __inline void
ia64_st4(uint32_t * p,uint32_t v)356 ia64_st4(uint32_t *p, uint32_t v)
357 {
358 	__asm __volatile("st4 [%0]=%1;;" :: "r"(p), "r"(v));
359 }
360 
361 static __inline void
ia64_st8(uint64_t * p,uint64_t v)362 ia64_st8(uint64_t *p, uint64_t v)
363 {
364 	__asm __volatile("st8 [%0]=%1;;" :: "r"(p), "r"(v));
365 }
366 
367 /*
368  * Read the value of psr.
369  */
370 static __inline uint64_t
ia64_get_psr(void)371 ia64_get_psr(void)
372 {
373 	uint64_t result;
374 	__asm __volatile("mov %0=psr;;" : "=r" (result));
375 	return result;
376 }
377 
378 /*
379  * Define accessors for application registers.
380  */
381 
382 #define IA64_AR(name)						\
383 								\
384 static __inline uint64_t					\
385 ia64_get_##name(void)						\
386 {								\
387 	uint64_t result;					\
388 	__asm __volatile("mov %0=ar." #name : "=r" (result));	\
389 	return result;						\
390 }								\
391 								\
392 static __inline void						\
393 ia64_set_##name(uint64_t v)					\
394 {								\
395 	__asm __volatile("mov ar." #name "=%0;;" :: "r" (v));	\
396 }
397 
398 IA64_AR(k0)
IA64_AR(k1)399 IA64_AR(k1)
400 IA64_AR(k2)
401 IA64_AR(k3)
402 IA64_AR(k4)
403 IA64_AR(k5)
404 IA64_AR(k6)
405 IA64_AR(k7)
406 
407 IA64_AR(rsc)
408 IA64_AR(bsp)
409 IA64_AR(bspstore)
410 IA64_AR(rnat)
411 
412 IA64_AR(fcr)
413 
414 IA64_AR(eflag)
415 IA64_AR(csd)
416 IA64_AR(ssd)
417 IA64_AR(cflg)
418 IA64_AR(fsr)
419 IA64_AR(fir)
420 IA64_AR(fdr)
421 
422 IA64_AR(ccv)
423 
424 IA64_AR(unat)
425 
426 IA64_AR(fpsr)
427 
428 IA64_AR(itc)
429 
430 IA64_AR(pfs)
431 IA64_AR(lc)
432 IA64_AR(ec)
433 
434 /*
435  * Define accessors for control registers.
436  */
437 
438 #define IA64_CR(name)						\
439 								\
440 static __inline uint64_t					\
441 ia64_get_##name(void)						\
442 {								\
443 	uint64_t result;					\
444 	__asm __volatile("mov %0=cr." #name : "=r" (result));	\
445 	return result;						\
446 }								\
447 								\
448 static __inline void						\
449 ia64_set_##name(uint64_t v)					\
450 {								\
451 	__asm __volatile("mov cr." #name "=%0;;" :: "r" (v));	\
452 }
453 
454 IA64_CR(dcr)
455 IA64_CR(itm)
456 IA64_CR(iva)
457 
458 IA64_CR(pta)
459 
460 IA64_CR(ipsr)
461 IA64_CR(isr)
462 
463 IA64_CR(iip)
464 IA64_CR(ifa)
465 IA64_CR(itir)
466 IA64_CR(iipa)
467 IA64_CR(ifs)
468 IA64_CR(iim)
469 IA64_CR(iha)
470 
471 IA64_CR(lid)
472 IA64_CR(ivr)
473 IA64_CR(tpr)
474 IA64_CR(eoi)
475 IA64_CR(irr0)
476 IA64_CR(irr1)
477 IA64_CR(irr2)
478 IA64_CR(irr3)
479 IA64_CR(itv)
480 IA64_CR(pmv)
481 IA64_CR(cmcv)
482 
483 IA64_CR(lrr0)
484 IA64_CR(lrr1)
485 
486 /*
487  * Write a region register.
488  */
489 static __inline void
490 ia64_set_rr(uint64_t rrbase, uint64_t v)
491 {
492 	__asm __volatile("mov rr[%0]=%1"
493 			 :: "r"(rrbase), "r"(v) : "memory");
494 }
495 
496 /*
497  * Read a CPUID register.
498  */
499 static __inline uint64_t
ia64_get_cpuid(int i)500 ia64_get_cpuid(int i)
501 {
502 	uint64_t result;
503 	__asm __volatile("mov %0=cpuid[%1]"
504 			 : "=r" (result) : "r"(i));
505 	return result;
506 }
507 
508 static __inline void
ia64_disable_highfp(void)509 ia64_disable_highfp(void)
510 {
511 	__asm __volatile("ssm psr.dfh;; srlz.d");
512 }
513 
514 static __inline void
ia64_enable_highfp(void)515 ia64_enable_highfp(void)
516 {
517 	__asm __volatile("rsm psr.dfh;; srlz.d");
518 }
519 
520 /*
521  * Avoid inline functions for the following so that they still work
522  * correctly when inlining is not enabled (e.g. -O0). Function calls
523  * need data serialization after setting psr, which results in a
524  * hazard.
525  */
526 #define	ia64_srlz_d()	__asm __volatile("srlz.d")
527 #define	ia64_srlz_i()	__asm __volatile("srlz.i;;")
528 
529 #endif /* !LOCORE */
530 
531 #endif /* _MACHINE_IA64_CPU_H_ */
532 
533