~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-ia64/system.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _ASM_IA64_SYSTEM_H
  2 #define _ASM_IA64_SYSTEM_H
  3 
  4 /*
  5  * System defines. Note that this is included both from .c and .S
  6  * files, so it does only defines, not any C code.  This is based
  7  * on information published in the Processor Abstraction Layer
  8  * and the System Abstraction Layer manual.
  9  *
 10  * Copyright (C) 1998-2000 Hewlett-Packard Co
 11  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
 12  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
 13  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
 14  */
 15 #include <linux/config.h>
 16 
 17 #include <asm/page.h>
 18 
 19 #define KERNEL_START            (PAGE_OFFSET + 0x500000)
 20 
 21 /*
 22  * The following #defines must match with vmlinux.lds.S:
 23  */
 24 #define IVT_END_ADDR            (KERNEL_START + 0x8000)
 25 #define ZERO_PAGE_ADDR          (IVT_END_ADDR + 0*PAGE_SIZE)
 26 #define SWAPPER_PGD_ADDR        (IVT_END_ADDR + 1*PAGE_SIZE)
 27 
 28 #define GATE_ADDR               (0xa000000000000000 + PAGE_SIZE)
 29 
 30 #if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
 31     || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)
 32   /* Workaround for Errata 97.  */
 33 # define IA64_SEMFIX_INSN       mf;
 34 # define IA64_SEMFIX    "mf;"
 35 #else
 36 # define IA64_SEMFIX_INSN
 37 # define IA64_SEMFIX    ""
 38 #endif
 39 
 40 #ifndef __ASSEMBLY__
 41 
 42 #include <linux/kernel.h>
 43 #include <linux/types.h>
 44 
 45 struct pci_vector_struct {
 46         __u16 bus;      /* PCI Bus number */
 47         __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
 48         __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
 49         __u8 irq;       /* IRQ assigned */
 50 };
 51 
 52 extern struct ia64_boot_param {
 53         __u64 command_line;             /* physical address of command line arguments */
 54         __u64 efi_systab;               /* physical address of EFI system table */
 55         __u64 efi_memmap;               /* physical address of EFI memory map */
 56         __u64 efi_memmap_size;          /* size of EFI memory map */
 57         __u64 efi_memdesc_size;         /* size of an EFI memory map descriptor */
 58         __u32 efi_memdesc_version;      /* memory descriptor version */
 59         struct {
 60                 __u16 num_cols; /* number of columns on console output device */
 61                 __u16 num_rows; /* number of rows on console output device */
 62                 __u16 orig_x;   /* cursor's x position */
 63                 __u16 orig_y;   /* cursor's y position */
 64         } console_info;
 65         __u16 num_pci_vectors;  /* number of ACPI derived PCI IRQ's*/
 66         __u64 pci_vectors;      /* physical address of PCI data (pci_vector_struct)*/
 67         __u64 fpswa;            /* physical address of the the fpswa interface */
 68         __u64 initrd_start;
 69         __u64 initrd_size;
 70 } ia64_boot_param;
 71 
 72 static inline void
 73 ia64_insn_group_barrier (void)
 74 {
 75         __asm__ __volatile__ (";;" ::: "memory");
 76 }
 77 
 78 /*
 79  * Macros to force memory ordering.  In these descriptions, "previous"
 80  * and "subsequent" refer to program order; "visible" means that all
 81  * architecturally visible effects of a memory access have occurred
 82  * (at a minimum, this means the memory has been read or written).
 83  *
 84  *   wmb():     Guarantees that all preceding stores to memory-
 85  *              like regions are visible before any subsequent
 86  *              stores and that all following stores will be
 87  *              visible only after all previous stores.
 88  *   rmb():     Like wmb(), but for reads.
 89  *   mb():      wmb()/rmb() combo, i.e., all previous memory
 90  *              accesses are visible before all subsequent
 91  *              accesses and vice versa.  This is also known as
 92  *              a "fence."
 93  *
 94  * Note: "mb()" and its variants cannot be used as a fence to order
 95  * accesses to memory mapped I/O registers.  For that, mf.a needs to
 96  * be used.  However, we don't want to always use mf.a because (a)
 97  * it's (presumably) much slower than mf and (b) mf.a is supported for
 98  * sequential memory pages only.
 99  */
100 #define mb()    __asm__ __volatile__ ("mf" ::: "memory")
101 #define rmb()   mb()
102 #define wmb()   mb()
103 
104 #ifdef CONFIG_SMP
105 # define smp_mb()       mb()
106 # define smp_rmb()      rmb()
107 # define smp_wmb()      wmb()
108 #else
109 # define smp_mb()       barrier()
110 # define smp_rmb()      barrier()
111 # define smp_wmb()      barrier()
112 #endif
113 
114 /*
115  * XXX check on these---I suspect what Linus really wants here is
116  * acquire vs release semantics but we can't discuss this stuff with
117  * Linus just yet.  Grrr...
118  */
119 #define set_mb(var, value)      do { (var) = (value); mb(); } while (0)
120 #define set_wmb(var, value)     do { (var) = (value); mb(); } while (0)
121 
122 /*
123  * The group barrier in front of the rsm & ssm are necessary to ensure
124  * that none of the previous instructions in the same group are
125  * affected by the rsm/ssm.
126  */
127 /* For spinlocks etc */
128 
129 #ifdef CONFIG_IA64_DEBUG_IRQ
130 
131   extern unsigned long last_cli_ip;
132 
133 # define local_irq_save(x)                                                              \
134 do {                                                                                    \
135         unsigned long ip, psr;                                                          \
136                                                                                         \
137         __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory");     \
138         if (psr & (1UL << 14)) {                                                        \
139                 __asm__ ("mov %0=ip" : "=r"(ip));                                       \
140                 last_cli_ip = ip;                                                       \
141         }                                                                               \
142         (x) = psr;                                                                      \
143 } while (0)
144 
145 # define local_irq_disable()                                                            \
146 do {                                                                                    \
147         unsigned long ip, psr;                                                          \
148                                                                                         \
149         __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory");     \
150         if (psr & (1UL << 14)) {                                                        \
151                 __asm__ ("mov %0=ip" : "=r"(ip));                                       \
152                 last_cli_ip = ip;                                                       \
153         }                                                                               \
154 } while (0)
155 
156 # define local_irq_restore(x)                                            \
157 do {                                                                     \
158         unsigned long ip, old_psr, psr = (x);                            \
159                                                                          \
160         __asm__ __volatile__ (";;mov %0=psr; mov psr.l=%1;; srlz.d"      \
161                               : "=&r" (old_psr) : "r" (psr) : "memory"); \
162         if ((old_psr & (1UL << 14)) && !(psr & (1UL << 14))) {           \
163                 __asm__ ("mov %0=ip" : "=r"(ip));                        \
164                 last_cli_ip = ip;                                        \
165         }                                                                \
166 } while (0)
167 
168 #else /* !CONFIG_IA64_DEBUG_IRQ */
169   /* clearing of psr.i is implicitly serialized (visible by next insn) */
170 # define local_irq_save(x)      __asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;"        \
171                                                       : "=r" (x) :: "memory")
172 # define local_irq_disable()    __asm__ __volatile__ (";; rsm psr.i;;" ::: "memory")
173 /* (potentially) setting psr.i requires data serialization: */
174 # define local_irq_restore(x)   __asm__ __volatile__ (";; mov psr.l=%0;; srlz.d"        \
175                                                       :: "r" (x) : "memory")
176 #endif /* !CONFIG_IA64_DEBUG_IRQ */
177 
178 #define local_irq_enable()      __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory")
179 
180 #define __cli()                 local_irq_disable ()
181 #define __save_flags(flags)     __asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory")
182 #define __save_and_cli(flags)   local_irq_save(flags)
183 #define save_and_cli(flags)     __save_and_cli(flags)
184 
185 
186 #ifdef CONFIG_IA64_SOFTSDV_HACKS
187 /*
188  * Yech.  SoftSDV has a slight probem with psr.i and itc/itm.  If
189  * PSR.i = 0 and ITC == ITM, you don't get the timer tick posted.  So,
190  * I'll check if ITC is larger than ITM here and reset if neccessary.
191  * I may miss a tick to two.
192  * 
193  * Don't include asm/delay.h; it causes include loops that are
194  * mind-numbingly hard to follow.
195  */
196 
197 #define get_itc(x) __asm__ __volatile__("mov %0=ar.itc" : "=r"((x)) :: "memory")
198 #define get_itm(x) __asm__ __volatile__("mov %0=cr.itm" : "=r"((x)) :: "memory")
199 #define set_itm(x) __asm__ __volatile__("mov cr.itm=%0" :: "r"((x)) : "memory")
200 
201 #define __restore_flags(x)                      \
202 do {                                            \
203         unsigned long itc, itm;                 \
204         local_irq_restore(x);                   \
205         get_itc(itc);                           \
206         get_itm(itm);                           \
207         if (itc > itm)                          \
208                 set_itm(itc + 10);              \
209 } while (0)
210 
211 #define __sti()                                 \
212 do {                                            \
213         unsigned long itc, itm;                 \
214         local_irq_enable();                     \
215         get_itc(itc);                           \
216         get_itm(itm);                           \
217         if (itc > itm)                          \
218                 set_itm(itc + 10);              \
219 } while (0)
220 
221 #else /* !CONFIG_IA64_SOFTSDV_HACKS */
222 
223 #define __sti()                 local_irq_enable ()
224 #define __restore_flags(flags)  local_irq_restore(flags)
225 
226 #endif /* !CONFIG_IA64_SOFTSDV_HACKS */
227 
228 #ifdef CONFIG_SMP
229   extern void __global_cli (void);
230   extern void __global_sti (void);
231   extern unsigned long __global_save_flags (void);
232   extern void __global_restore_flags (unsigned long);
233 # define cli()                  __global_cli()
234 # define sti()                  __global_sti()
235 # define save_flags(flags)      ((flags) = __global_save_flags())
236 # define restore_flags(flags)   __global_restore_flags(flags)
237 #else /* !CONFIG_SMP */
238 # define cli()                  __cli()
239 # define sti()                  __sti()
240 # define save_flags(flags)      __save_flags(flags)
241 # define restore_flags(flags)   __restore_flags(flags)
242 #endif /* !CONFIG_SMP */
243 
244 /*
245  * Force an unresolved reference if someone tries to use
246  * ia64_fetch_and_add() with a bad value.
247  */
248 extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
249 extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
250 
251 #define IA64_FETCHADD(tmp,v,n,sz)                                               \
252 ({                                                                              \
253         switch (sz) {                                                           \
254               case 4:                                                           \
255                 __asm__ __volatile__ (IA64_SEMFIX"fetchadd4.rel %0=[%1],%2"     \
256                                       : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \
257                 break;                                                          \
258                                                                                 \
259               case 8:                                                           \
260                 __asm__ __volatile__ (IA64_SEMFIX"fetchadd8.rel %0=[%1],%2"     \
261                                       : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \
262                 break;                                                          \
263                                                                                 \
264               default:                                                          \
265                 __bad_size_for_ia64_fetch_and_add();                            \
266         }                                                                       \
267 })
268 
269 #define ia64_fetch_and_add(i,v)                                                 \
270 ({                                                                              \
271         __u64 _tmp;                                                             \
272         volatile __typeof__(*(v)) *_v = (v);                                    \
273         switch (i) {                                                            \
274               case -16: IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;      \
275               case  -8: IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;      \
276               case  -4: IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;      \
277               case  -1: IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;      \
278               case   1: IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;      \
279               case   4: IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;      \
280               case   8: IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;      \
281               case  16: IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;      \
282               default:                                                          \
283                 _tmp = __bad_increment_for_ia64_fetch_and_add();                \
284                 break;                                                          \
285         }                                                                       \
286         (__typeof__(*v)) (_tmp + (i));  /* return new value */                  \
287 })
288 
289 /*
290  * This function doesn't exist, so you'll get a linker error if
291  * something tries to do an invalid xchg().
292  */
293 extern void __xchg_called_with_bad_pointer (void);
294 
295 static __inline__ unsigned long
296 __xchg (unsigned long x, volatile void *ptr, int size)
297 {
298         unsigned long result;
299 
300         switch (size) {
301               case 1:
302                 __asm__ __volatile (IA64_SEMFIX"xchg1 %0=[%1],%2" : "=r" (result)
303                                     : "r" (ptr), "r" (x) : "memory");
304                 return result;
305 
306               case 2:
307                 __asm__ __volatile (IA64_SEMFIX"xchg2 %0=[%1],%2" : "=r" (result)
308                                     : "r" (ptr), "r" (x) : "memory");
309                 return result;
310 
311               case 4:
312                 __asm__ __volatile (IA64_SEMFIX"xchg4 %0=[%1],%2" : "=r" (result)
313                                     : "r" (ptr), "r" (x) : "memory");
314                 return result;
315 
316               case 8:
317                 __asm__ __volatile (IA64_SEMFIX"xchg8 %0=[%1],%2" : "=r" (result)
318                                     : "r" (ptr), "r" (x) : "memory");
319                 return result;
320         }
321         __xchg_called_with_bad_pointer();
322         return x;
323 }
324 
325 #define xchg(ptr,x)                                                          \
326   ((__typeof__(*(ptr))) __xchg ((unsigned long) (x), (ptr), sizeof(*(ptr))))
327 
328 /* 
329  * Atomic compare and exchange.  Compare OLD with MEM, if identical,
330  * store NEW in MEM.  Return the initial value in MEM.  Success is
331  * indicated by comparing RETURN with OLD.
332  */
333 
334 #define __HAVE_ARCH_CMPXCHG 1
335 
336 /*
337  * This function doesn't exist, so you'll get a linker error
338  * if something tries to do an invalid cmpxchg().
339  */
340 extern long __cmpxchg_called_with_bad_pointer(void);
341 
342 #define ia64_cmpxchg(sem,ptr,old,new,size)                                              \
343 ({                                                                                      \
344         __typeof__(ptr) _p_ = (ptr);                                                    \
345         __typeof__(new) _n_ = (new);                                                    \
346         __u64 _o_, _r_;                                                                 \
347                                                                                         \
348         switch (size) {                                                                 \
349               case 1: _o_ = (__u8 ) (long) (old); break;                                \
350               case 2: _o_ = (__u16) (long) (old); break;                                \
351               case 4: _o_ = (__u32) (long) (old); break;                                \
352               case 8: _o_ = (__u64) (long) (old); break;                                \
353               default:                                                                  \
354         }                                                                               \
355          __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_));                         \
356         switch (size) {                                                                 \
357               case 1:                                                                   \
358                 __asm__ __volatile__ (IA64_SEMFIX"cmpxchg1."sem" %0=[%1],%2,ar.ccv"     \
359                                       : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");     \
360                 break;                                                                  \
361                                                                                         \
362               case 2:                                                                   \
363                 __asm__ __volatile__ (IA64_SEMFIX"cmpxchg2."sem" %0=[%1],%2,ar.ccv"     \
364                                       : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");     \
365                 break;                                                                  \
366                                                                                         \
367               case 4:                                                                   \
368                 __asm__ __volatile__ (IA64_SEMFIX"cmpxchg4."sem" %0=[%1],%2,ar.ccv"     \
369                                       : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");     \
370                 break;                                                                  \
371                                                                                         \
372               case 8:                                                                   \
373                 __asm__ __volatile__ (IA64_SEMFIX"cmpxchg8."sem" %0=[%1],%2,ar.ccv"     \
374                                       : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory");     \
375                 break;                                                                  \
376                                                                                         \
377               default:                                                                  \
378                 _r_ = __cmpxchg_called_with_bad_pointer();                              \
379                 break;                                                                  \
380         }                                                                               \
381         (__typeof__(old)) _r_;                                                          \
382 })
383 
384 #define cmpxchg_acq(ptr,o,n)    ia64_cmpxchg("acq", (ptr), (o), (n), sizeof(*(ptr)))
385 #define cmpxchg_rel(ptr,o,n)    ia64_cmpxchg("rel", (ptr), (o), (n), sizeof(*(ptr)))
386 
387 /* for compatibility with other platforms: */
388 #define cmpxchg(ptr,o,n)        cmpxchg_acq(ptr,o,n)
389 
390 #ifdef CONFIG_IA64_DEBUG_CMPXCHG
391 # define CMPXCHG_BUGCHECK_DECL  int _cmpxchg_bugcheck_count = 128;
392 # define CMPXCHG_BUGCHECK(v)                                                    \
393   do {                                                                          \
394         if (_cmpxchg_bugcheck_count-- <= 0) {                                   \
395                 void *ip;                                                       \
396                 extern int printk(const char *fmt, ...);                        \
397                 asm ("mov %0=ip" : "=r"(ip));                                   \
398                 printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));  \
399                 break;                                                          \
400         }                                                                       \
401   } while (0)
402 #else /* !CONFIG_IA64_DEBUG_CMPXCHG */
403 # define CMPXCHG_BUGCHECK_DECL
404 # define CMPXCHG_BUGCHECK(v)
405 #endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
406 
407 #ifdef __KERNEL__
408 
409 #define prepare_to_switch()    do { } while(0)
410 
411 #ifdef CONFIG_IA32_SUPPORT
412 # define IS_IA32_PROCESS(regs)  (ia64_psr(regs)->is != 0)
413 #else
414 # define IS_IA32_PROCESS(regs)          0
415 #endif
416 
417 /*
418  * Context switch from one thread to another.  If the two threads have
419  * different address spaces, schedule() has already taken care of
420  * switching to the new address space by calling switch_mm().
421  *
422  * Disabling access to the fph partition and the debug-register
423  * context switch MUST be done before calling ia64_switch_to() since a
424  * newly created thread returns directly to
425  * ia64_ret_from_syscall_clear_r8.
426  */
427 extern struct task_struct *ia64_switch_to (void *next_task);
428 
429 extern void ia64_save_extra (struct task_struct *task);
430 extern void ia64_load_extra (struct task_struct *task);
431 
432 #define __switch_to(prev,next,last) do {                                                \
433         if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))       \
434             || IS_IA32_PROCESS(ia64_task_regs(prev)))                                   \
435                 ia64_save_extra(prev);                                                  \
436         if (((next)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))       \
437             || IS_IA32_PROCESS(ia64_task_regs(next)))                                   \
438                 ia64_load_extra(next);                                                  \
439         (last) = ia64_switch_to((next));                                                \
440 } while (0)
441 
442 #ifdef CONFIG_SMP 
443   /*
444    * In the SMP case, we save the fph state when context-switching
445    * away from a thread that modified fph.  This way, when the thread
446    * gets scheduled on another CPU, the CPU can pick up the state from
447    * task->thread.fph, avoiding the complication of having to fetch
448    * the latest fph state from another CPU.
449    */
450 # define switch_to(prev,next,last) do {                                         \
451         if (ia64_psr(ia64_task_regs(prev))->mfh) {                              \
452                 ia64_psr(ia64_task_regs(prev))->mfh = 0;                        \
453                 (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  \
454                 __ia64_save_fpu((prev)->thread.fph);                            \
455         }                                                                       \
456         ia64_psr(ia64_task_regs(prev))->dfh = 1;                                \
457         __switch_to(prev,next,last);                                            \
458   } while (0)
459 #else
460 # define switch_to(prev,next,last) do {                                         \
461         ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next)); \
462         __switch_to(prev,next,last);                                            \
463 } while (0)
464 #endif
465 
466 #endif /* __KERNEL__ */
467 
468 #endif /* __ASSEMBLY__ */
469 
470 #endif /* _ASM_IA64_SYSTEM_H */
471 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.