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

Linux Cross Reference
Linux/include/asm-parisc/processor.h

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

  1 /*
  2  * include/asm-parisc/processor.h
  3  *
  4  * Copyright (C) 1994 Linus Torvalds
  5  */
  6 
  7 #ifndef __ASM_PARISC_PROCESSOR_H
  8 #define __ASM_PARISC_PROCESSOR_H
  9 
 10 #ifndef __ASSEMBLY__
 11 #include <linux/threads.h>
 12 
 13 #include <asm/hardware.h>
 14 #include <asm/page.h>
 15 #include <asm/pdc.h>
 16 #include <asm/ptrace.h>
 17 #include <asm/types.h>
 18 #endif /* __ASSEMBLY__ */
 19 
 20 /*
 21  * Default implementation of macro that returns current
 22  * instruction pointer ("program counter").
 23  */
 24 
 25 /* We cannot use MFIA as it was added for PA2.0 - prumpf
 26 
 27    At one point there were no "0f/0b" type local symbols in gas for
 28    PA-RISC.  This is no longer true, but this still seems like the
 29    nicest way to implement this. */
 30 
 31 #define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; })
 32 
 33 #define TASK_SIZE           (PAGE_OFFSET)
 34 #define TASK_UNMAPPED_BASE  (TASK_SIZE / 3)
 35 
 36 #ifndef __ASSEMBLY__
 37 
 38 /*
 39 ** Data detected about CPUs at boot time which is the same for all CPU's.
 40 ** HP boxes are SMP - ie identical processors.
 41 **
 42 ** FIXME: some CPU rev info may be processor specific...
 43 */
 44 struct system_cpuinfo_parisc {
 45         unsigned int    cpu_count;
 46         unsigned int    cpu_hz;
 47         unsigned int    hversion;
 48         unsigned int    sversion;
 49         enum cpu_type   cpu_type;
 50 
 51         struct {
 52                 struct pdc_model model;
 53                 struct pdc_model_cpuid /* ARGH */ versions;
 54                 struct pdc_model_cpuid cpuid;
 55 #if 0
 56                 struct pdc_model_caps caps;
 57 #endif
 58                 char   sys_model_name[81]; /* PDC-ROM returnes this model name */
 59         } pdc;
 60 
 61         char            *model_name;
 62         char            *cpu_name;
 63         char            *family_name;
 64 };
 65 
 66 
 67 /*
 68 ** Per CPU data structure - ie varies per CPU.
 69 */
 70 struct cpuinfo_parisc {
 71         unsigned cpuid;
 72 
 73         struct irq_region *region;
 74 
 75         unsigned long it_value; /* Interval Timer value at last timer interrupt */
 76         unsigned long it_delta; /* Interval Timer delta (tic_10ms / HZ * 100) */
 77 
 78         unsigned long hpa;      /* Host Physical address */
 79         unsigned long txn_addr; /* External Interrupt Register or id_eid */
 80 
 81         unsigned long bh_count;         /* number of times bh was invoked */
 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 };
 85 
 86 extern struct system_cpuinfo_parisc boot_cpu_data;
 87 extern struct cpuinfo_parisc cpu_data[NR_CPUS];
 88 #define current_cpu_data cpu_data[smp_processor_id()]
 89 
 90 extern void identify_cpu(struct cpuinfo_parisc *);
 91 
 92 #define EISA_bus 0 /* we don't have ISA support yet */
 93 #define EISA_bus__is_a_macro /* for versions in ksyms.c */
 94 #define MCA_bus 0
 95 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 96 
 97 typedef struct {
 98         int seg;  
 99 } mm_segment_t;
100 
101 struct thread_struct {
102         struct pt_regs regs;
103         unsigned long  pg_tables;
104         unsigned long  flags;
105 }; 
106 
107 /* Thread struct flags. */
108 #define PARISC_KERNEL_DEATH     (1UL << 31)     /* see die_if_kernel()... */
109 
110 #define INIT_MMAP { &init_mm, 0, 0, NULL, PAGE_SHARED, \
111                     VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
112 
113 #define INIT_THREAD { {                 \
114         { 0, 0, 0, 0, 0, 0, 0, 0,       \
115           0, 0, 0, 0, 0, 0, 0, 0,       \
116           0, 0, 0, 0, 0, 0, 0, 0,       \
117           0, 0, 0, 0, 0, 0, 0, 0 },     \
118         { 0, 0, 0, 0, 0, 0, 0, 0,       \
119           0, 0, 0, 0, 0, 0, 0, 0,       \
120           0, 0, 0, 0, 0, 0, 0, 0,       \
121           0, 0, 0, 0, 0, 0, 0, 0 },     \
122         { 0, 0, 0, 0, 0, 0, 0, 0 },     \
123         { 0, 0}, { 0, 0}, 0, 0, 0, 0    \
124         }, __pa((unsigned long) swapper_pg_dir) }
125 
126 /*
127  * Return saved PC of a blocked thread.  This is used by ps mostly.
128  */
129 
130 extern inline unsigned long thread_saved_pc(struct thread_struct *t)
131 {
132         return 0xabcdef;
133 }
134 
135 /*
136  * Start user thread in another space.
137  *
138  * Note that we set both the iaoq and r31 to the new pc. When
139  * the kernel initially calls execve it will return through an
140  * rfi path that will use the values in the iaoq. The execve
141  * syscall path will return through the gateway page, and
142  * that uses r31 to branch to.
143  *
144  * For ELF we clear r23, because the dynamic linker uses it to pass
145  * the address of the finalizer function.
146  *
147  * We also initialize sr3 to an illegal value (illegal for our
148  * implementation, not for the architecture).
149  */
150 
151 /* The ELF abi wants things done a "wee bit" differently than
152  * som does.  Supporting this behavior here avoids
153  * having our own version of create_elf_tables.
154  *
155  * Oh, and yes, that is not a typo, we are really passing argc in r25
156  * and argv in r24 (rather than r26 and r25).  This is because that's
157  * where __libc_start_main wants them.
158  *
159  * Duplicated from dl-machine.h for the benefit of readers:
160  *
161  *  Our initial stack layout is rather different from everyone else's
162  *  due to the unique PA-RISC ABI.  As far as I know it looks like
163  *  this:
164 
165    -----------------------------------  (user startup code creates this frame)
166    |         32 bytes of magic       |
167    |---------------------------------|
168    | 32 bytes argument/sp save area  |
169    |---------------------------------|  ((current->mm->env_end) + 63 & ~63)
170    |         N bytes of slack        |
171    |---------------------------------|
172    |      envvar and arg strings     |
173    |---------------------------------|
174    |        ELF auxiliary info       |
175    |         (up to 28 words)        |
176    |---------------------------------|
177    |  Environment variable pointers  |
178    |         upwards to NULL         |
179    |---------------------------------|
180    |        Argument pointers        |
181    |         upwards to NULL         |
182    |---------------------------------|
183    |          argc (1 word)          |
184    -----------------------------------
185 
186  *  The pleasant part of this is that if we need to skip arguments we
187  *  can just decrement argc and move argv, because the stack pointer
188  *  is utterly unrelated to the location of the environment and
189  *  argument vectors.
190  *
191  * Note that the S/390 people took the easy way out and hacked their
192  * GCC to make the stack grow downwards.  */
193 
194 #define start_thread_som(regs, new_pc, new_sp) do {             \
195         unsigned long *sp = (unsigned long *)new_sp;    \
196         __u32 spaceid = (__u32)current->mm->context;    \
197         unsigned long pc = (unsigned long)new_pc;       \
198         /* offset pc for priv. level */                 \
199         pc |= 3;                                        \
200                                                         \
201         set_fs(USER_DS);                                \
202         regs->iasq[0] = spaceid;                        \
203         regs->iasq[1] = spaceid;                        \
204         regs->iaoq[0] = pc;                             \
205         regs->iaoq[1] = pc;                             \
206         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
207         regs->sr[3] = 0xffff;                           \
208         regs->sr[4] = spaceid;                          \
209         regs->sr[5] = spaceid;                          \
210         regs->sr[6] = spaceid;                          \
211         regs->sr[7] = spaceid;                          \
212         regs->gr[ 0] = USER_INIT_PSW;                   \
213         regs->gr[30] = ((new_sp)+63)&~63;               \
214         regs->gr[31] = pc;                              \
215                                                         \
216         get_user(regs->gr[26],&sp[0]);                  \
217         get_user(regs->gr[25],&sp[-1]);                 \
218         get_user(regs->gr[24],&sp[-2]);                 \
219         get_user(regs->gr[23],&sp[-3]);                 \
220                                                         \
221         regs->cr30 = (u32) current;                     \
222 } while(0)
223 
224 
225 #define start_thread(regs, new_pc, new_sp) do {         \
226         unsigned long *sp = (unsigned long *)new_sp;    \
227         __u32 spaceid = (__u32)current->mm->context;    \
228         unsigned long pc = (unsigned long)new_pc;       \
229         /* offset pc for priv. level */                 \
230         pc |= 3;                                        \
231                                                         \
232                                                         \
233         set_fs(USER_DS);                                \
234         regs->iasq[0] = spaceid;                        \
235         regs->iasq[1] = spaceid;                        \
236         regs->iaoq[0] = pc;                             \
237         regs->iaoq[1] = pc;                             \
238         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
239         regs->sr[3] = 0xffff;                           \
240         regs->sr[4] = spaceid;                          \
241         regs->sr[5] = spaceid;                          \
242         regs->sr[6] = spaceid;                          \
243         regs->sr[7] = spaceid;                          \
244         regs->gr[ 0] = USER_INIT_PSW;                   \
245         regs->fr[ 0] = 0LL;                             \
246         regs->fr[ 1] = 0LL;                             \
247         regs->fr[ 2] = 0LL;                             \
248         regs->fr[ 3] = 0LL;                             \
249         regs->gr[30] = ((current->mm->env_end)+63)&~63; \
250         regs->gr[31] = pc;                              \
251                                                         \
252         get_user(regs->gr[25],&sp[0]);                  \
253         regs->gr[24] = (unsigned long) &sp[1];          \
254         regs->gr[23] = 0;                               \
255                                                         \
256         regs->cr30 = (u32) current;                     \
257 } while(0)
258 
259 #ifdef __LP64__
260 
261 /*
262  * For 64 bit kernels we need a version of start thread for 32 bit
263  * elf files.
264  *
265  * FIXME: It should be possible to not duplicate the above code
266  *        by playing games with concatenation to form both
267  *        macros at compile time. The only difference between
268  *        this macro and the above is the name and the types
269  *        for sp and pc.
270  */
271 
272 #define start_thread32(regs, new_pc, new_sp) do {         \
273         __u32 *sp = (__u32 *)new_sp;                    \
274         __u32 spaceid = (__u32)current->mm->context;    \
275         __u32 pc = (__u32)new_pc;                       \
276         /* offset pc for priv. level */                 \
277         pc |= 3;                                        \
278                                                         \
279         set_fs(USER_DS);                                \
280         regs->iasq[0] = spaceid;                        \
281         regs->iasq[1] = spaceid;                        \
282         regs->iaoq[0] = pc;                             \
283         regs->iaoq[1] = pc;                             \
284         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
285         regs->sr[3] = 0xffff;                           \
286         regs->sr[4] = spaceid;                          \
287         regs->sr[5] = spaceid;                          \
288         regs->sr[6] = spaceid;                          \
289         regs->sr[7] = spaceid;                          \
290         regs->gr[ 0] = USER_INIT_PSW;                   \
291         regs->fr[ 0] = 0LL;                             \
292         regs->fr[ 1] = 0LL;                             \
293         regs->fr[ 2] = 0LL;                             \
294         regs->fr[ 3] = 0LL;                             \
295         regs->gr[30] = ((current->mm->env_end)+63)&~63; \
296         regs->gr[31] = pc;                              \
297                                                         \
298         get_user(regs->gr[25],&sp[0]);                  \
299         regs->gr[24] = (unsigned long) &sp[1];          \
300         regs->gr[23] = 0;                               \
301                                                         \
302         regs->cr30 = (u32) current;                     \
303 } while(0)
304 
305 #endif
306 
307 struct task_struct;
308 
309 /* Free all resources held by a thread. */
310 extern void release_thread(struct task_struct *);
311 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
312 
313 #define copy_segments(tsk, mm)  do { } while (0)
314 #define release_segments(mm)    do { } while (0)
315 
316 extern inline unsigned long get_wchan(struct task_struct *p)
317 {
318         return 0xdeadbeef; /* XXX */
319 }
320 
321 #define KSTK_EIP(tsk)   (0xdeadbeef)
322 #define KSTK_ESP(tsk)   (0xdeadbeef)
323 
324 /* Be sure to hunt all references to this down when you change the size of
325  * the kernel stack */
326 
327 #endif /* __ASSEMBLY__ */
328 
329 #define THREAD_SIZE     (4*PAGE_SIZE)
330 
331 #define alloc_task_struct() \
332         ((struct task_struct *) __get_free_pages(GFP_KERNEL,2))
333 #define free_task_struct(p)     free_pages((unsigned long)(p),2)
334 #define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
335 
336 #define init_task (init_task_union.task) 
337 #define init_stack (init_task_union.stack)
338 
339 
340 #endif /* __ASM_PARISC_PROCESSOR_H */
341 

~ [ 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.