system.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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