aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/include/asm/processor.h
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2008-08-01 13:13:32 -0400
committerTony Luck <tony.luck@intel.com>2008-08-01 13:21:21 -0400
commit7f30491ccd28627742e37899453ae20e3da8e18f (patch)
tree7291c0a26ed3a31acf9542857af3981d278f5de8 /arch/ia64/include/asm/processor.h
parent94ad374a0751f40d25e22e036c37f7263569d24c (diff)
[IA64] Move include/asm-ia64 to arch/ia64/include/asm
After moving the the include files there were a few clean-ups: 1) Some files used #include <asm-ia64/xyz.h>, changed to <asm/xyz.h> 2) Some comments alerted maintainers to look at various header files to make matching updates if certain code were to be changed. Updated these comments to use the new include paths. 3) Some header files mentioned their own names in initial comments. Just deleted these self references. Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/include/asm/processor.h')
-rw-r--r--arch/ia64/include/asm/processor.h771
1 files changed, 771 insertions, 0 deletions
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
new file mode 100644
index 000000000000..f88fa054d01d
--- /dev/null
+++ b/arch/ia64/include/asm/processor.h
@@ -0,0 +1,771 @@
1#ifndef _ASM_IA64_PROCESSOR_H
2#define _ASM_IA64_PROCESSOR_H
3
4/*
5 * Copyright (C) 1998-2004 Hewlett-Packard Co
6 * David Mosberger-Tang <davidm@hpl.hp.com>
7 * Stephane Eranian <eranian@hpl.hp.com>
8 * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
9 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
10 *
11 * 11/24/98 S.Eranian added ia64_set_iva()
12 * 12/03/99 D. Mosberger implement thread_saved_pc() via kernel unwind API
13 * 06/16/00 A. Mallick added csd/ssd/tssd for ia32 support
14 */
15
16
17#include <asm/intrinsics.h>
18#include <asm/kregs.h>
19#include <asm/ptrace.h>
20#include <asm/ustack.h>
21
22#define IA64_NUM_PHYS_STACK_REG 96
23#define IA64_NUM_DBG_REGS 8
24
25#define DEFAULT_MAP_BASE __IA64_UL_CONST(0x2000000000000000)
26#define DEFAULT_TASK_SIZE __IA64_UL_CONST(0xa000000000000000)
27
28/*
29 * TASK_SIZE really is a mis-named. It really is the maximum user
30 * space address (plus one). On IA-64, there are five regions of 2TB
31 * each (assuming 8KB page size), for a total of 8TB of user virtual
32 * address space.
33 */
34#define TASK_SIZE_OF(tsk) ((tsk)->thread.task_size)
35#define TASK_SIZE TASK_SIZE_OF(current)
36
37/*
38 * This decides where the kernel will search for a free chunk of vm
39 * space during mmap's.
40 */
41#define TASK_UNMAPPED_BASE (current->thread.map_base)
42
43#define IA64_THREAD_FPH_VALID (__IA64_UL(1) << 0) /* floating-point high state valid? */
44#define IA64_THREAD_DBG_VALID (__IA64_UL(1) << 1) /* debug registers valid? */
45#define IA64_THREAD_PM_VALID (__IA64_UL(1) << 2) /* performance registers valid? */
46#define IA64_THREAD_UAC_NOPRINT (__IA64_UL(1) << 3) /* don't log unaligned accesses */
47#define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4) /* generate SIGBUS on unaligned acc. */
48#define IA64_THREAD_MIGRATION (__IA64_UL(1) << 5) /* require migration
49 sync at ctx sw */
50#define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6) /* don't log any fpswa faults */
51#define IA64_THREAD_FPEMU_SIGFPE (__IA64_UL(1) << 7) /* send a SIGFPE for fpswa faults */
52
53#define IA64_THREAD_UAC_SHIFT 3
54#define IA64_THREAD_UAC_MASK (IA64_THREAD_UAC_NOPRINT | IA64_THREAD_UAC_SIGBUS)
55#define IA64_THREAD_FPEMU_SHIFT 6
56#define IA64_THREAD_FPEMU_MASK (IA64_THREAD_FPEMU_NOPRINT | IA64_THREAD_FPEMU_SIGFPE)
57
58
59/*
60 * This shift should be large enough to be able to represent 1000000000/itc_freq with good
61 * accuracy while being small enough to fit 10*1000000000<<IA64_NSEC_PER_CYC_SHIFT in 64 bits
62 * (this will give enough slack to represent 10 seconds worth of time as a scaled number).
63 */
64#define IA64_NSEC_PER_CYC_SHIFT 30
65
66#ifndef __ASSEMBLY__
67
68#include <linux/cache.h>
69#include <linux/compiler.h>
70#include <linux/threads.h>
71#include <linux/types.h>
72
73#include <asm/fpu.h>
74#include <asm/page.h>
75#include <asm/percpu.h>
76#include <asm/rse.h>
77#include <asm/unwind.h>
78#include <asm/atomic.h>
79#ifdef CONFIG_NUMA
80#include <asm/nodedata.h>
81#endif
82
83/* like above but expressed as bitfields for more efficient access: */
84struct ia64_psr {
85 __u64 reserved0 : 1;
86 __u64 be : 1;
87 __u64 up : 1;
88 __u64 ac : 1;
89 __u64 mfl : 1;
90 __u64 mfh : 1;
91 __u64 reserved1 : 7;
92 __u64 ic : 1;
93 __u64 i : 1;
94 __u64 pk : 1;
95 __u64 reserved2 : 1;
96 __u64 dt : 1;
97 __u64 dfl : 1;
98 __u64 dfh : 1;
99 __u64 sp : 1;
100 __u64 pp : 1;
101 __u64 di : 1;
102 __u64 si : 1;
103 __u64 db : 1;
104 __u64 lp : 1;
105 __u64 tb : 1;
106 __u64 rt : 1;
107 __u64 reserved3 : 4;
108 __u64 cpl : 2;
109 __u64 is : 1;
110 __u64 mc : 1;
111 __u64 it : 1;
112 __u64 id : 1;
113 __u64 da : 1;
114 __u64 dd : 1;
115 __u64 ss : 1;
116 __u64 ri : 2;
117 __u64 ed : 1;
118 __u64 bn : 1;
119 __u64 reserved4 : 19;
120};
121
122union ia64_isr {
123 __u64 val;
124 struct {
125 __u64 code : 16;
126 __u64 vector : 8;
127 __u64 reserved1 : 8;
128 __u64 x : 1;
129 __u64 w : 1;
130 __u64 r : 1;
131 __u64 na : 1;
132 __u64 sp : 1;
133 __u64 rs : 1;
134 __u64 ir : 1;
135 __u64 ni : 1;
136 __u64 so : 1;
137 __u64 ei : 2;
138 __u64 ed : 1;
139 __u64 reserved2 : 20;
140 };
141};
142
143union ia64_lid {
144 __u64 val;
145 struct {
146 __u64 rv : 16;
147 __u64 eid : 8;
148 __u64 id : 8;
149 __u64 ig : 32;
150 };
151};
152
153union ia64_tpr {
154 __u64 val;
155 struct {
156 __u64 ig0 : 4;
157 __u64 mic : 4;
158 __u64 rsv : 8;
159 __u64 mmi : 1;
160 __u64 ig1 : 47;
161 };
162};
163
164union ia64_itir {
165 __u64 val;
166 struct {
167 __u64 rv3 : 2; /* 0-1 */
168 __u64 ps : 6; /* 2-7 */
169 __u64 key : 24; /* 8-31 */
170 __u64 rv4 : 32; /* 32-63 */
171 };
172};
173
174union ia64_rr {
175 __u64 val;
176 struct {
177 __u64 ve : 1; /* enable hw walker */
178 __u64 reserved0: 1; /* reserved */
179 __u64 ps : 6; /* log page size */
180 __u64 rid : 24; /* region id */
181 __u64 reserved1: 32; /* reserved */
182 };
183};
184
185/*
186 * CPU type, hardware bug flags, and per-CPU state. Frequently used
187 * state comes earlier:
188 */
189struct cpuinfo_ia64 {
190 __u32 softirq_pending;
191 __u64 itm_delta; /* # of clock cycles between clock ticks */
192 __u64 itm_next; /* interval timer mask value to use for next clock tick */
193 __u64 nsec_per_cyc; /* (1000000000<<IA64_NSEC_PER_CYC_SHIFT)/itc_freq */
194 __u64 unimpl_va_mask; /* mask of unimplemented virtual address bits (from PAL) */
195 __u64 unimpl_pa_mask; /* mask of unimplemented physical address bits (from PAL) */
196 __u64 itc_freq; /* frequency of ITC counter */
197 __u64 proc_freq; /* frequency of processor */
198 __u64 cyc_per_usec; /* itc_freq/1000000 */
199 __u64 ptce_base;
200 __u32 ptce_count[2];
201 __u32 ptce_stride[2];
202 struct task_struct *ksoftirqd; /* kernel softirq daemon for this CPU */
203
204#ifdef CONFIG_SMP
205 __u64 loops_per_jiffy;
206 int cpu;
207 __u32 socket_id; /* physical processor socket id */
208 __u16 core_id; /* core id */
209 __u16 thread_id; /* thread id */
210 __u16 num_log; /* Total number of logical processors on
211 * this socket that were successfully booted */
212 __u8 cores_per_socket; /* Cores per processor socket */
213 __u8 threads_per_core; /* Threads per core */
214#endif
215
216 /* CPUID-derived information: */
217 __u64 ppn;
218 __u64 features;
219 __u8 number;
220 __u8 revision;
221 __u8 model;
222 __u8 family;
223 __u8 archrev;
224 char vendor[16];
225 char *model_name;
226
227#ifdef CONFIG_NUMA
228 struct ia64_node_data *node_data;
229#endif
230};
231
232DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
233
234/*
235 * The "local" data variable. It refers to the per-CPU data of the currently executing
236 * CPU, much like "current" points to the per-task data of the currently executing task.
237 * Do not use the address of local_cpu_data, since it will be different from
238 * cpu_data(smp_processor_id())!
239 */
240#define local_cpu_data (&__ia64_per_cpu_var(cpu_info))
241#define cpu_data(cpu) (&per_cpu(cpu_info, cpu))
242
243extern void print_cpu_info (struct cpuinfo_ia64 *);
244
245typedef struct {
246 unsigned long seg;
247} mm_segment_t;
248
249#define SET_UNALIGN_CTL(task,value) \
250({ \
251 (task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_UAC_MASK) \
252 | (((value) << IA64_THREAD_UAC_SHIFT) & IA64_THREAD_UAC_MASK)); \
253 0; \
254})
255#define GET_UNALIGN_CTL(task,addr) \
256({ \
257 put_user(((task)->thread.flags & IA64_THREAD_UAC_MASK) >> IA64_THREAD_UAC_SHIFT, \
258 (int __user *) (addr)); \
259})
260
261#define SET_FPEMU_CTL(task,value) \
262({ \
263 (task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_FPEMU_MASK) \
264 | (((value) << IA64_THREAD_FPEMU_SHIFT) & IA64_THREAD_FPEMU_MASK)); \
265 0; \
266})
267#define GET_FPEMU_CTL(task,addr) \
268({ \
269 put_user(((task)->thread.flags & IA64_THREAD_FPEMU_MASK) >> IA64_THREAD_FPEMU_SHIFT, \
270 (int __user *) (addr)); \
271})
272
273#ifdef CONFIG_IA32_SUPPORT
274struct desc_struct {
275 unsigned int a, b;
276};
277
278#define desc_empty(desc) (!((desc)->a | (desc)->b))
279#define desc_equal(desc1, desc2) (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
280
281#define GDT_ENTRY_TLS_ENTRIES 3
282#define GDT_ENTRY_TLS_MIN 6
283#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
284
285#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
286
287struct ia64_partial_page_list;
288#endif
289
290struct thread_struct {
291 __u32 flags; /* various thread flags (see IA64_THREAD_*) */
292 /* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
293 __u8 on_ustack; /* executing on user-stacks? */
294 __u8 pad[3];
295 __u64 ksp; /* kernel stack pointer */
296 __u64 map_base; /* base address for get_unmapped_area() */
297 __u64 task_size; /* limit for task size */
298 __u64 rbs_bot; /* the base address for the RBS */
299 int last_fph_cpu; /* CPU that may hold the contents of f32-f127 */
300
301#ifdef CONFIG_IA32_SUPPORT
302 __u64 eflag; /* IA32 EFLAGS reg */
303 __u64 fsr; /* IA32 floating pt status reg */
304 __u64 fcr; /* IA32 floating pt control reg */
305 __u64 fir; /* IA32 fp except. instr. reg */
306 __u64 fdr; /* IA32 fp except. data reg */
307 __u64 old_k1; /* old value of ar.k1 */
308 __u64 old_iob; /* old IOBase value */
309 struct ia64_partial_page_list *ppl; /* partial page list for 4K page size issue */
310 /* cached TLS descriptors. */
311 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
312
313# define INIT_THREAD_IA32 .eflag = 0, \
314 .fsr = 0, \
315 .fcr = 0x17800000037fULL, \
316 .fir = 0, \
317 .fdr = 0, \
318 .old_k1 = 0, \
319 .old_iob = 0, \
320 .ppl = NULL,
321#else
322# define INIT_THREAD_IA32
323#endif /* CONFIG_IA32_SUPPORT */
324#ifdef CONFIG_PERFMON
325 void *pfm_context; /* pointer to detailed PMU context */
326 unsigned long pfm_needs_checking; /* when >0, pending perfmon work on kernel exit */
327# define INIT_THREAD_PM .pfm_context = NULL, \
328 .pfm_needs_checking = 0UL,
329#else
330# define INIT_THREAD_PM
331#endif
332 __u64 dbr[IA64_NUM_DBG_REGS];
333 __u64 ibr[IA64_NUM_DBG_REGS];
334 struct ia64_fpreg fph[96]; /* saved/loaded on demand */
335};
336
337#define INIT_THREAD { \
338 .flags = 0, \
339 .on_ustack = 0, \
340 .ksp = 0, \
341 .map_base = DEFAULT_MAP_BASE, \
342 .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
343 .task_size = DEFAULT_TASK_SIZE, \
344 .last_fph_cpu = -1, \
345 INIT_THREAD_IA32 \
346 INIT_THREAD_PM \
347 .dbr = {0, }, \
348 .ibr = {0, }, \
349 .fph = {{{{0}}}, } \
350}
351
352#define start_thread(regs,new_ip,new_sp) do { \
353 set_fs(USER_DS); \
354 regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL)) \
355 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS)); \
356 regs->cr_iip = new_ip; \
357 regs->ar_rsc = 0xf; /* eager mode, privilege level 3 */ \
358 regs->ar_rnat = 0; \
359 regs->ar_bspstore = current->thread.rbs_bot; \
360 regs->ar_fpsr = FPSR_DEFAULT; \
361 regs->loadrs = 0; \
362 regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \
363 regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \
364 if (unlikely(!get_dumpable(current->mm))) { \
365 /* \
366 * Zap scratch regs to avoid leaking bits between processes with different \
367 * uid/privileges. \
368 */ \
369 regs->ar_pfs = 0; regs->b0 = 0; regs->pr = 0; \
370 regs->r1 = 0; regs->r9 = 0; regs->r11 = 0; regs->r13 = 0; regs->r15 = 0; \
371 } \
372} while (0)
373
374/* Forward declarations, a strange C thing... */
375struct mm_struct;
376struct task_struct;
377
378/*
379 * Free all resources held by a thread. This is called after the
380 * parent of DEAD_TASK has collected the exit status of the task via
381 * wait().
382 */
383#define release_thread(dead_task)
384
385/* Prepare to copy thread state - unlazy all lazy status */
386#define prepare_to_copy(tsk) do { } while (0)
387
388/*
389 * This is the mechanism for creating a new kernel thread.
390 *
391 * NOTE 1: Only a kernel-only process (ie the swapper or direct
392 * descendants who haven't done an "execve()") should use this: it
393 * will work within a system call from a "real" process, but the
394 * process memory space will not be free'd until both the parent and
395 * the child have exited.
396 *
397 * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get
398 * into trouble in init/main.c when the child thread returns to
399 * do_basic_setup() and the timing is such that free_initmem() has
400 * been called already.
401 */
402extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);
403
404/* Get wait channel for task P. */
405extern unsigned long get_wchan (struct task_struct *p);
406
407/* Return instruction pointer of blocked task TSK. */
408#define KSTK_EIP(tsk) \
409 ({ \
410 struct pt_regs *_regs = task_pt_regs(tsk); \
411 _regs->cr_iip + ia64_psr(_regs)->ri; \
412 })
413
414/* Return stack pointer of blocked task TSK. */
415#define KSTK_ESP(tsk) ((tsk)->thread.ksp)
416
417extern void ia64_getreg_unknown_kr (void);
418extern void ia64_setreg_unknown_kr (void);
419
420#define ia64_get_kr(regnum) \
421({ \
422 unsigned long r = 0; \
423 \
424 switch (regnum) { \
425 case 0: r = ia64_getreg(_IA64_REG_AR_KR0); break; \
426 case 1: r = ia64_getreg(_IA64_REG_AR_KR1); break; \
427 case 2: r = ia64_getreg(_IA64_REG_AR_KR2); break; \
428 case 3: r = ia64_getreg(_IA64_REG_AR_KR3); break; \
429 case 4: r = ia64_getreg(_IA64_REG_AR_KR4); break; \
430 case 5: r = ia64_getreg(_IA64_REG_AR_KR5); break; \
431 case 6: r = ia64_getreg(_IA64_REG_AR_KR6); break; \
432 case 7: r = ia64_getreg(_IA64_REG_AR_KR7); break; \
433 default: ia64_getreg_unknown_kr(); break; \
434 } \
435 r; \
436})
437
438#define ia64_set_kr(regnum, r) \
439({ \
440 switch (regnum) { \
441 case 0: ia64_setreg(_IA64_REG_AR_KR0, r); break; \
442 case 1: ia64_setreg(_IA64_REG_AR_KR1, r); break; \
443 case 2: ia64_setreg(_IA64_REG_AR_KR2, r); break; \
444 case 3: ia64_setreg(_IA64_REG_AR_KR3, r); break; \
445 case 4: ia64_setreg(_IA64_REG_AR_KR4, r); break; \
446 case 5: ia64_setreg(_IA64_REG_AR_KR5, r); break; \
447 case 6: ia64_setreg(_IA64_REG_AR_KR6, r); break; \
448 case 7: ia64_setreg(_IA64_REG_AR_KR7, r); break; \
449 default: ia64_setreg_unknown_kr(); break; \
450 } \
451})
452
453/*
454 * The following three macros can't be inline functions because we don't have struct
455 * task_struct at this point.
456 */
457
458/*
459 * Return TRUE if task T owns the fph partition of the CPU we're running on.
460 * Must be called from code that has preemption disabled.
461 */
462#define ia64_is_local_fpu_owner(t) \
463({ \
464 struct task_struct *__ia64_islfo_task = (t); \
465 (__ia64_islfo_task->thread.last_fph_cpu == smp_processor_id() \
466 && __ia64_islfo_task == (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER)); \
467})
468
469/*
470 * Mark task T as owning the fph partition of the CPU we're running on.
471 * Must be called from code that has preemption disabled.
472 */
473#define ia64_set_local_fpu_owner(t) do { \
474 struct task_struct *__ia64_slfo_task = (t); \
475 __ia64_slfo_task->thread.last_fph_cpu = smp_processor_id(); \
476 ia64_set_kr(IA64_KR_FPU_OWNER, (unsigned long) __ia64_slfo_task); \
477} while (0)
478
479/* Mark the fph partition of task T as being invalid on all CPUs. */
480#define ia64_drop_fpu(t) ((t)->thread.last_fph_cpu = -1)
481
482extern void __ia64_init_fpu (void);
483extern void __ia64_save_fpu (struct ia64_fpreg *fph);
484extern void __ia64_load_fpu (struct ia64_fpreg *fph);
485extern void ia64_save_debug_regs (unsigned long *save_area);
486extern void ia64_load_debug_regs (unsigned long *save_area);
487
488#ifdef CONFIG_IA32_SUPPORT
489extern void ia32_save_state (struct task_struct *task);
490extern void ia32_load_state (struct task_struct *task);
491#endif
492
493#define ia64_fph_enable() do { ia64_rsm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
494#define ia64_fph_disable() do { ia64_ssm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
495
496/* load fp 0.0 into fph */
497static inline void
498ia64_init_fpu (void) {
499 ia64_fph_enable();
500 __ia64_init_fpu();
501 ia64_fph_disable();
502}
503
504/* save f32-f127 at FPH */
505static inline void
506ia64_save_fpu (struct ia64_fpreg *fph) {
507 ia64_fph_enable();
508 __ia64_save_fpu(fph);
509 ia64_fph_disable();
510}
511
512/* load f32-f127 from FPH */
513static inline void
514ia64_load_fpu (struct ia64_fpreg *fph) {
515 ia64_fph_enable();
516 __ia64_load_fpu(fph);
517 ia64_fph_disable();
518}
519
520static inline __u64
521ia64_clear_ic (void)
522{
523 __u64 psr;
524 psr = ia64_getreg(_IA64_REG_PSR);
525 ia64_stop();
526 ia64_rsm(IA64_PSR_I | IA64_PSR_IC);
527 ia64_srlz_i();
528 return psr;
529}
530
531/*
532 * Restore the psr.
533 */
534static inline void
535ia64_set_psr (__u64 psr)
536{
537 ia64_stop();
538 ia64_setreg(_IA64_REG_PSR_L, psr);
539 ia64_srlz_i();
540}
541
542/*
543 * Insert a translation into an instruction and/or data translation
544 * register.
545 */
546static inline void
547ia64_itr (__u64 target_mask, __u64 tr_num,
548 __u64 vmaddr, __u64 pte,
549 __u64 log_page_size)
550{
551 ia64_setreg(_IA64_REG_CR_ITIR, (log_page_size << 2));
552 ia64_setreg(_IA64_REG_CR_IFA, vmaddr);
553 ia64_stop();
554 if (target_mask & 0x1)
555 ia64_itri(tr_num, pte);
556 if (target_mask & 0x2)
557 ia64_itrd(tr_num, pte);
558}
559
560/*
561 * Insert a translation into the instruction and/or data translation
562 * cache.
563 */
564static inline void
565ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte,
566 __u64 log_page_size)
567{
568 ia64_setreg(_IA64_REG_CR_ITIR, (log_page_size << 2));
569 ia64_setreg(_IA64_REG_CR_IFA, vmaddr);
570 ia64_stop();
571 /* as per EAS2.6, itc must be the last instruction in an instruction group */
572 if (target_mask & 0x1)
573 ia64_itci(pte);
574 if (target_mask & 0x2)
575 ia64_itcd(pte);
576}
577
578/*
579 * Purge a range of addresses from instruction and/or data translation
580 * register(s).
581 */
582static inline void
583ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size)
584{
585 if (target_mask & 0x1)
586 ia64_ptri(vmaddr, (log_size << 2));
587 if (target_mask & 0x2)
588 ia64_ptrd(vmaddr, (log_size << 2));
589}
590
591/* Set the interrupt vector address. The address must be suitably aligned (32KB). */
592static inline void
593ia64_set_iva (void *ivt_addr)
594{
595 ia64_setreg(_IA64_REG_CR_IVA, (__u64) ivt_addr);
596 ia64_srlz_i();
597}
598
599/* Set the page table address and control bits. */
600static inline void
601ia64_set_pta (__u64 pta)
602{
603 /* Note: srlz.i implies srlz.d */
604 ia64_setreg(_IA64_REG_CR_PTA, pta);
605 ia64_srlz_i();
606}
607
608static inline void
609ia64_eoi (void)
610{
611 ia64_setreg(_IA64_REG_CR_EOI, 0);
612 ia64_srlz_d();
613}
614
615#define cpu_relax() ia64_hint(ia64_hint_pause)
616
617static inline int
618ia64_get_irr(unsigned int vector)
619{
620 unsigned int reg = vector / 64;
621 unsigned int bit = vector % 64;
622 u64 irr;
623
624 switch (reg) {
625 case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break;
626 case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break;
627 case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break;
628 case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break;
629 }
630
631 return test_bit(bit, &irr);
632}
633
634static inline void
635ia64_set_lrr0 (unsigned long val)
636{
637 ia64_setreg(_IA64_REG_CR_LRR0, val);
638 ia64_srlz_d();
639}
640
641static inline void
642ia64_set_lrr1 (unsigned long val)
643{
644 ia64_setreg(_IA64_REG_CR_LRR1, val);
645 ia64_srlz_d();
646}
647
648
649/*
650 * Given the address to which a spill occurred, return the unat bit
651 * number that corresponds to this address.
652 */
653static inline __u64
654ia64_unat_pos (void *spill_addr)
655{
656 return ((__u64) spill_addr >> 3) & 0x3f;
657}
658
659/*
660 * Set the NaT bit of an integer register which was spilled at address
661 * SPILL_ADDR. UNAT is the mask to be updated.
662 */
663static inline void
664ia64_set_unat (__u64 *unat, void *spill_addr, unsigned long nat)
665{
666 __u64 bit = ia64_unat_pos(spill_addr);
667 __u64 mask = 1UL << bit;
668
669 *unat = (*unat & ~mask) | (nat << bit);
670}
671
672/*
673 * Return saved PC of a blocked thread.
674 * Note that the only way T can block is through a call to schedule() -> switch_to().
675 */
676static inline unsigned long
677thread_saved_pc (struct task_struct *t)
678{
679 struct unw_frame_info info;
680 unsigned long ip;
681
682 unw_init_from_blocked_task(&info, t);
683 if (unw_unwind(&info) < 0)
684 return 0;
685 unw_get_ip(&info, &ip);
686 return ip;
687}
688
689/*
690 * Get the current instruction/program counter value.
691 */
692#define current_text_addr() \
693 ({ void *_pc; _pc = (void *)ia64_getreg(_IA64_REG_IP); _pc; })
694
695static inline __u64
696ia64_get_ivr (void)
697{
698 __u64 r;
699 ia64_srlz_d();
700 r = ia64_getreg(_IA64_REG_CR_IVR);
701 ia64_srlz_d();
702 return r;
703}
704
705static inline void
706ia64_set_dbr (__u64 regnum, __u64 value)
707{
708 __ia64_set_dbr(regnum, value);
709#ifdef CONFIG_ITANIUM
710 ia64_srlz_d();
711#endif
712}
713
714static inline __u64
715ia64_get_dbr (__u64 regnum)
716{
717 __u64 retval;
718
719 retval = __ia64_get_dbr(regnum);
720#ifdef CONFIG_ITANIUM
721 ia64_srlz_d();
722#endif
723 return retval;
724}
725
726static inline __u64
727ia64_rotr (__u64 w, __u64 n)
728{
729 return (w >> n) | (w << (64 - n));
730}
731
732#define ia64_rotl(w,n) ia64_rotr((w), (64) - (n))
733
734/*
735 * Take a mapped kernel address and return the equivalent address
736 * in the region 7 identity mapped virtual area.
737 */
738static inline void *
739ia64_imva (void *addr)
740{
741 void *result;
742 result = (void *) ia64_tpa(addr);
743 return __va(result);
744}
745
746#define ARCH_HAS_PREFETCH
747#define ARCH_HAS_PREFETCHW
748#define ARCH_HAS_SPINLOCK_PREFETCH
749#define PREFETCH_STRIDE L1_CACHE_BYTES
750
751static inline void
752prefetch (const void *x)
753{
754 ia64_lfetch(ia64_lfhint_none, x);
755}
756
757static inline void
758prefetchw (const void *x)
759{
760 ia64_lfetch_excl(ia64_lfhint_none, x);
761}
762
763#define spin_lock_prefetch(x) prefetchw(x)
764
765extern unsigned long boot_option_idle_override;
766extern unsigned long idle_halt;
767extern unsigned long idle_nomwait;
768
769#endif /* !__ASSEMBLY__ */
770
771#endif /* _ASM_IA64_PROCESSOR_H */