home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-parisc / processor.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  11.3 KB  |  362 lines

  1. /*
  2.  * include/asm-parisc/processor.h
  3.  *
  4.  * Copyright (C) 1994 Linus Torvalds
  5.  * Copyright (C) 2001 Grant Grundler
  6.  */
  7.  
  8. #ifndef __ASM_PARISC_PROCESSOR_H
  9. #define __ASM_PARISC_PROCESSOR_H
  10.  
  11. #ifndef __ASSEMBLY__
  12. #include <linux/threads.h>
  13. #include <linux/spinlock_types.h>
  14.  
  15. #include <asm/hardware.h>
  16. #include <asm/page.h>
  17. #include <asm/pdc.h>
  18. #include <asm/ptrace.h>
  19. #include <asm/types.h>
  20. #include <asm/system.h>
  21. #endif /* __ASSEMBLY__ */
  22.  
  23. #define KERNEL_STACK_SIZE     (4*PAGE_SIZE)
  24.  
  25. /*
  26.  * Default implementation of macro that returns current
  27.  * instruction pointer ("program counter").
  28.  */
  29. #ifdef CONFIG_PA20
  30. #define current_ia(x)    __asm__("mfia %0" : "=r"(x))
  31. #else /* mfia added in pa2.0 */
  32. #define current_ia(x)    __asm__("blr 0,%0\n\tnop" : "=r"(x))
  33. #endif
  34. #define current_text_addr() ({ void *pc; current_ia(pc); pc; })
  35.  
  36. #define TASK_SIZE               (current->thread.task_size)
  37. #define TASK_UNMAPPED_BASE      (current->thread.map_base)
  38.  
  39. #define DEFAULT_TASK_SIZE32    (0xFFF00000UL)
  40. #define DEFAULT_MAP_BASE32    (0x40000000UL)
  41.  
  42. #ifdef __LP64__
  43. #define DEFAULT_TASK_SIZE       (MAX_ADDRESS-0xf000000)
  44. #define DEFAULT_MAP_BASE        (0x200000000UL)
  45. #else
  46. #define DEFAULT_TASK_SIZE    DEFAULT_TASK_SIZE32
  47. #define DEFAULT_MAP_BASE    DEFAULT_MAP_BASE32
  48. #endif
  49.  
  50. #ifndef __ASSEMBLY__
  51.  
  52. /*
  53.  * Data detected about CPUs at boot time which is the same for all CPU's.
  54.  * HP boxes are SMP - ie identical processors.
  55.  *
  56.  * FIXME: some CPU rev info may be processor specific...
  57.  */
  58. struct system_cpuinfo_parisc {
  59.     unsigned int    cpu_count;
  60.     unsigned int    cpu_hz;
  61.     unsigned int    hversion;
  62.     unsigned int    sversion;
  63.     enum cpu_type    cpu_type;
  64.  
  65.     struct {
  66.         struct pdc_model model;
  67.         unsigned long versions;
  68.         unsigned long cpuid;
  69.         unsigned long capabilities;
  70.         char   sys_model_name[81]; /* PDC-ROM returnes this model name */
  71.     } pdc;
  72.  
  73.     char        *cpu_name;    /* e.g. "PA7300LC (PCX-L2)" */
  74.     char        *family_name;    /* e.g. "1.1e" */
  75. };
  76.  
  77.  
  78. /* Per CPU data structure - ie varies per CPU.  */
  79. struct cpuinfo_parisc {
  80.     unsigned long it_value;     /* Interval Timer at last timer Intr */
  81.     unsigned long it_delta;     /* Interval delta (tic_10ms / HZ * 100) */
  82.     unsigned long irq_count;    /* number of IRQ's since boot */
  83.     unsigned long irq_max_cr16; /* longest time to handle a single IRQ */
  84.     unsigned long cpuid;        /* aka slot_number or set to NO_PROC_ID */
  85.     unsigned long hpa;          /* Host Physical address */
  86.     unsigned long txn_addr;     /* MMIO addr of EIR or id_eid */
  87. #ifdef CONFIG_SMP
  88.     spinlock_t lock;            /* synchronization for ipi's */
  89.     unsigned long pending_ipi;  /* bitmap of type ipi_message_type */
  90.     unsigned long ipi_count;    /* number ipi Interrupts */
  91. #endif
  92.     unsigned long bh_count;     /* number of times bh was invoked */
  93.     unsigned long prof_counter; /* per CPU profiling support */
  94.     unsigned long prof_multiplier;    /* per CPU profiling support */
  95.     unsigned long fp_rev;
  96.     unsigned long fp_model;
  97.     unsigned int state;
  98.     struct parisc_device *dev;
  99.     unsigned long loops_per_jiffy;
  100. };
  101.  
  102. extern struct system_cpuinfo_parisc boot_cpu_data;
  103. extern struct cpuinfo_parisc cpu_data[NR_CPUS];
  104. #define current_cpu_data cpu_data[smp_processor_id()]
  105.  
  106. #define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
  107.  
  108. typedef struct {
  109.     int seg;  
  110. } mm_segment_t;
  111.  
  112. #define ARCH_MIN_TASKALIGN    8
  113.  
  114. struct thread_struct {
  115.     struct pt_regs regs;
  116.     unsigned long  task_size;
  117.     unsigned long  map_base;
  118.     unsigned long  flags;
  119. }; 
  120.  
  121. /* Thread struct flags. */
  122. #define PARISC_UAC_NOPRINT    (1UL << 0)    /* see prctl and unaligned.c */
  123. #define PARISC_UAC_SIGBUS    (1UL << 1)
  124. #define PARISC_KERNEL_DEATH    (1UL << 31)    /* see die_if_kernel()... */
  125.  
  126. #define PARISC_UAC_SHIFT    0
  127. #define PARISC_UAC_MASK        (PARISC_UAC_NOPRINT|PARISC_UAC_SIGBUS)
  128.  
  129. #define SET_UNALIGN_CTL(task,value)                                       \
  130.         ({                                                                \
  131.         (task)->thread.flags = (((task)->thread.flags & ~PARISC_UAC_MASK) \
  132.                                 | (((value) << PARISC_UAC_SHIFT) &        \
  133.                                    PARISC_UAC_MASK));                     \
  134.         0;                                                                \
  135.         })
  136.  
  137. #define GET_UNALIGN_CTL(task,addr)                                        \
  138.         ({                                                                \
  139.         put_user(((task)->thread.flags & PARISC_UAC_MASK)                 \
  140.                  >> PARISC_UAC_SHIFT, (int __user *) (addr));             \
  141.         })
  142.  
  143. #define INIT_THREAD { \
  144.     .regs = {    .gr    = { 0, }, \
  145.             .fr    = { 0, }, \
  146.             .sr    = { 0, }, \
  147.             .iasq    = { 0, }, \
  148.             .iaoq    = { 0, }, \
  149.             .cr27    = 0, \
  150.         }, \
  151.     .task_size    = DEFAULT_TASK_SIZE, \
  152.     .map_base    = DEFAULT_MAP_BASE, \
  153.     .flags        = 0 \
  154.     }
  155.  
  156. /*
  157.  * Return saved PC of a blocked thread.  This is used by ps mostly.
  158.  */
  159.  
  160. unsigned long thread_saved_pc(struct task_struct *t);
  161. void show_trace(struct task_struct *task, unsigned long *stack);
  162.  
  163. /*
  164.  * Start user thread in another space.
  165.  *
  166.  * Note that we set both the iaoq and r31 to the new pc. When
  167.  * the kernel initially calls execve it will return through an
  168.  * rfi path that will use the values in the iaoq. The execve
  169.  * syscall path will return through the gateway page, and
  170.  * that uses r31 to branch to.
  171.  *
  172.  * For ELF we clear r23, because the dynamic linker uses it to pass
  173.  * the address of the finalizer function.
  174.  *
  175.  * We also initialize sr3 to an illegal value (illegal for our
  176.  * implementation, not for the architecture).
  177.  */
  178. typedef unsigned int elf_caddr_t;
  179.  
  180. #define start_thread_som(regs, new_pc, new_sp) do {    \
  181.     unsigned long *sp = (unsigned long *)new_sp;    \
  182.     __u32 spaceid = (__u32)current->mm->context;    \
  183.     unsigned long pc = (unsigned long)new_pc;    \
  184.     /* offset pc for priv. level */            \
  185.     pc |= 3;                    \
  186.                             \
  187.     set_fs(USER_DS);                \
  188.     regs->iasq[0] = spaceid;            \
  189.     regs->iasq[1] = spaceid;            \
  190.     regs->iaoq[0] = pc;                \
  191.     regs->iaoq[1] = pc + 4;                         \
  192.     regs->sr[2] = LINUX_GATEWAY_SPACE;              \
  193.     regs->sr[3] = 0xffff;                \
  194.     regs->sr[4] = spaceid;                \
  195.     regs->sr[5] = spaceid;                \
  196.     regs->sr[6] = spaceid;                \
  197.     regs->sr[7] = spaceid;                \
  198.     regs->gr[ 0] = USER_PSW;                        \
  199.     regs->gr[30] = ((new_sp)+63)&~63;        \
  200.     regs->gr[31] = pc;                \
  201.                             \
  202.     get_user(regs->gr[26],&sp[0]);            \
  203.     get_user(regs->gr[25],&sp[-1]);         \
  204.     get_user(regs->gr[24],&sp[-2]);         \
  205.     get_user(regs->gr[23],&sp[-3]);         \
  206. } while(0)
  207.  
  208. /* The ELF abi wants things done a "wee bit" differently than
  209.  * som does.  Supporting this behavior here avoids
  210.  * having our own version of create_elf_tables.
  211.  *
  212.  * Oh, and yes, that is not a typo, we are really passing argc in r25
  213.  * and argv in r24 (rather than r26 and r25).  This is because that's
  214.  * where __libc_start_main wants them.
  215.  *
  216.  * Duplicated from dl-machine.h for the benefit of readers:
  217.  *
  218.  *  Our initial stack layout is rather different from everyone else's
  219.  *  due to the unique PA-RISC ABI.  As far as I know it looks like
  220.  *  this:
  221.  
  222.    -----------------------------------  (user startup code creates this frame)
  223.    |         32 bytes of magic       |
  224.    |---------------------------------|
  225.    | 32 bytes argument/sp save area  |
  226.    |---------------------------------| (bprm->p)
  227.    |        ELF auxiliary info         |
  228.    |         (up to 28 words)        |
  229.    |---------------------------------|
  230.    |           NULL             |
  231.    |---------------------------------|
  232.    |       Environment pointers         |
  233.    |---------------------------------|
  234.    |           NULL             |
  235.    |---------------------------------|
  236.    |        Argument pointers        |
  237.    |---------------------------------| <- argv
  238.    |          argc (1 word)          |
  239.    |---------------------------------| <- bprm->exec (HACK!)
  240.    |         N bytes of slack        |
  241.    |---------------------------------|
  242.    |    filename passed to execve    |
  243.    |---------------------------------| (mm->env_end)
  244.    |           env strings           |
  245.    |---------------------------------| (mm->env_start, mm->arg_end)
  246.    |           arg strings           |
  247.    |---------------------------------|
  248.    | additional faked arg strings if |
  249.    | we're invoked via binfmt_script |
  250.    |---------------------------------| (mm->arg_start)
  251.    stack base is at TASK_SIZE - rlim_max.
  252.  
  253. on downward growing arches, it looks like this:
  254.    stack base at TASK_SIZE
  255.    | filename passed to execve
  256.    | env strings
  257.    | arg strings
  258.    | faked arg strings
  259.    | slack
  260.    | ELF
  261.    | envps
  262.    | argvs
  263.    | argc
  264.  
  265.  *  The pleasant part of this is that if we need to skip arguments we
  266.  *  can just decrement argc and move argv, because the stack pointer
  267.  *  is utterly unrelated to the location of the environment and
  268.  *  argument vectors.
  269.  *
  270.  * Note that the S/390 people took the easy way out and hacked their
  271.  * GCC to make the stack grow downwards.
  272.  *
  273.  * Final Note: For entry from syscall, the W (wide) bit of the PSW
  274.  * is stuffed into the lowest bit of the user sp (%r30), so we fill
  275.  * it in here from the current->personality
  276.  */
  277.  
  278. #ifdef __LP64__
  279. #define USER_WIDE_MODE    (personality(current->personality) == PER_LINUX)
  280. #else
  281. #define USER_WIDE_MODE    0
  282. #endif
  283.  
  284. #define start_thread(regs, new_pc, new_sp) do {        \
  285.     elf_addr_t *sp = (elf_addr_t *)new_sp;        \
  286.     __u32 spaceid = (__u32)current->mm->context;    \
  287.     elf_addr_t pc = (elf_addr_t)new_pc | 3;        \
  288.     elf_caddr_t *argv = (elf_caddr_t *)bprm->exec + 1;    \
  289.                             \
  290.     set_fs(USER_DS);                \
  291.     regs->iasq[0] = spaceid;            \
  292.     regs->iasq[1] = spaceid;            \
  293.     regs->iaoq[0] = pc;                \
  294.     regs->iaoq[1] = pc + 4;                         \
  295.     regs->sr[2] = LINUX_GATEWAY_SPACE;              \
  296.     regs->sr[3] = 0xffff;                \
  297.     regs->sr[4] = spaceid;                \
  298.     regs->sr[5] = spaceid;                \
  299.     regs->sr[6] = spaceid;                \
  300.     regs->sr[7] = spaceid;                \
  301.     regs->gr[ 0] = USER_PSW | (USER_WIDE_MODE ? PSW_W : 0); \
  302.     regs->fr[ 0] = 0LL;                                \
  303.     regs->fr[ 1] = 0LL;                                \
  304.     regs->fr[ 2] = 0LL;                                \
  305.     regs->fr[ 3] = 0LL;                                \
  306.     regs->gr[30] = (((unsigned long)sp + 63) &~ 63) | (USER_WIDE_MODE ? 1 : 0); \
  307.     regs->gr[31] = pc;                \
  308.                             \
  309.     get_user(regs->gr[25], (argv - 1));        \
  310.     regs->gr[24] = (long) argv;            \
  311.     regs->gr[23] = 0;                \
  312. } while(0)
  313.  
  314. struct task_struct;
  315. struct mm_struct;
  316.  
  317. /* Free all resources held by a thread. */
  318. extern void release_thread(struct task_struct *);
  319. extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
  320.  
  321. /* Prepare to copy thread state - unlazy all lazy status */
  322. #define prepare_to_copy(tsk)    do { } while (0)
  323.  
  324. extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
  325.  
  326. extern unsigned long get_wchan(struct task_struct *p);
  327.  
  328. #define KSTK_EIP(tsk)    ((tsk)->thread.regs.iaoq[0])
  329. #define KSTK_ESP(tsk)    ((tsk)->thread.regs.gr[30])
  330.  
  331.  
  332. /*
  333.  * PA 2.0 defines data prefetch instructions on page 6-11 of the Kane book.
  334.  * In addition, many implementations do hardware prefetching of both
  335.  * instructions and data.
  336.  *
  337.  * PA7300LC (page 14-4 of the ERS) also implements prefetching by a load
  338.  * to gr0 but not in a way that Linux can use.  If the load would cause an
  339.  * interruption (eg due to prefetching 0), it is suppressed on PA2.0
  340.  * processors, but not on 7300LC.
  341.  */
  342. #ifdef  CONFIG_PREFETCH
  343. #define ARCH_HAS_PREFETCH
  344. #define ARCH_HAS_PREFETCHW
  345.  
  346. extern inline void prefetch(const void *addr)
  347. {
  348.     __asm__("ldw 0(%0), %%r0" : : "r" (addr));
  349. }
  350.  
  351. extern inline void prefetchw(const void *addr)
  352. {
  353.     __asm__("ldd 0(%0), %%r0" : : "r" (addr));
  354. }
  355. #endif
  356.  
  357. #define cpu_relax()    barrier()
  358.  
  359. #endif /* __ASSEMBLY__ */
  360.  
  361. #endif /* __ASM_PARISC_PROCESSOR_H */
  362.