v2.4.10.4 -> v2.4.10.5
[opensuse:kernel.git] / include / asm-parisc / processor.h
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_THREAD { {                 \
111         { 0, 0, 0, 0, 0, 0, 0, 0,       \
112           0, 0, 0, 0, 0, 0, 0, 0,       \
113           0, 0, 0, 0, 0, 0, 0, 0,       \
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         }, __pa((unsigned long) swapper_pg_dir) }
122
123 /*
124  * Return saved PC of a blocked thread.  This is used by ps mostly.
125  */
126
127 extern inline unsigned long thread_saved_pc(struct thread_struct *t)
128 {
129         return 0xabcdef;
130 }
131
132 /*
133  * Start user thread in another space.
134  *
135  * Note that we set both the iaoq and r31 to the new pc. When
136  * the kernel initially calls execve it will return through an
137  * rfi path that will use the values in the iaoq. The execve
138  * syscall path will return through the gateway page, and
139  * that uses r31 to branch to.
140  *
141  * For ELF we clear r23, because the dynamic linker uses it to pass
142  * the address of the finalizer function.
143  *
144  * We also initialize sr3 to an illegal value (illegal for our
145  * implementation, not for the architecture).
146  */
147
148 /* The ELF abi wants things done a "wee bit" differently than
149  * som does.  Supporting this behavior here avoids
150  * having our own version of create_elf_tables.
151  *
152  * Oh, and yes, that is not a typo, we are really passing argc in r25
153  * and argv in r24 (rather than r26 and r25).  This is because that's
154  * where __libc_start_main wants them.
155  *
156  * Duplicated from dl-machine.h for the benefit of readers:
157  *
158  *  Our initial stack layout is rather different from everyone else's
159  *  due to the unique PA-RISC ABI.  As far as I know it looks like
160  *  this:
161
162    -----------------------------------  (user startup code creates this frame)
163    |         32 bytes of magic       |
164    |---------------------------------|
165    | 32 bytes argument/sp save area  |
166    |---------------------------------|  ((current->mm->env_end) + 63 & ~63)
167    |         N bytes of slack        |
168    |---------------------------------|
169    |      envvar and arg strings     |
170    |---------------------------------|
171    |        ELF auxiliary info       |
172    |         (up to 28 words)        |
173    |---------------------------------|
174    |  Environment variable pointers  |
175    |         upwards to NULL         |
176    |---------------------------------|
177    |        Argument pointers        |
178    |         upwards to NULL         |
179    |---------------------------------|
180    |          argc (1 word)          |
181    -----------------------------------
182
183  *  The pleasant part of this is that if we need to skip arguments we
184  *  can just decrement argc and move argv, because the stack pointer
185  *  is utterly unrelated to the location of the environment and
186  *  argument vectors.
187  *
188  * Note that the S/390 people took the easy way out and hacked their
189  * GCC to make the stack grow downwards.  */
190
191 #define start_thread_som(regs, new_pc, new_sp) do {             \
192         unsigned long *sp = (unsigned long *)new_sp;    \
193         __u32 spaceid = (__u32)current->mm->context;    \
194         unsigned long pc = (unsigned long)new_pc;       \
195         /* offset pc for priv. level */                 \
196         pc |= 3;                                        \
197                                                         \
198         set_fs(USER_DS);                                \
199         regs->iasq[0] = spaceid;                        \
200         regs->iasq[1] = spaceid;                        \
201         regs->iaoq[0] = pc;                             \
202         regs->iaoq[1] = pc;                             \
203         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
204         regs->sr[3] = 0xffff;                           \
205         regs->sr[4] = spaceid;                          \
206         regs->sr[5] = spaceid;                          \
207         regs->sr[6] = spaceid;                          \
208         regs->sr[7] = spaceid;                          \
209         regs->gr[ 0] = USER_INIT_PSW;                   \
210         regs->gr[30] = ((new_sp)+63)&~63;               \
211         regs->gr[31] = pc;                              \
212                                                         \
213         get_user(regs->gr[26],&sp[0]);                  \
214         get_user(regs->gr[25],&sp[-1]);                 \
215         get_user(regs->gr[24],&sp[-2]);                 \
216         get_user(regs->gr[23],&sp[-3]);                 \
217                                                         \
218         regs->cr30 = (u32) current;                     \
219 } while(0)
220
221
222 #define start_thread(regs, new_pc, new_sp) do {         \
223         unsigned long *sp = (unsigned long *)new_sp;    \
224         __u32 spaceid = (__u32)current->mm->context;    \
225         unsigned long pc = (unsigned long)new_pc;       \
226         /* offset pc for priv. level */                 \
227         pc |= 3;                                        \
228                                                         \
229                                                         \
230         set_fs(USER_DS);                                \
231         regs->iasq[0] = spaceid;                        \
232         regs->iasq[1] = spaceid;                        \
233         regs->iaoq[0] = pc;                             \
234         regs->iaoq[1] = pc;                             \
235         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
236         regs->sr[3] = 0xffff;                           \
237         regs->sr[4] = spaceid;                          \
238         regs->sr[5] = spaceid;                          \
239         regs->sr[6] = spaceid;                          \
240         regs->sr[7] = spaceid;                          \
241         regs->gr[ 0] = USER_INIT_PSW;                   \
242         regs->fr[ 0] = 0LL;                             \
243         regs->fr[ 1] = 0LL;                             \
244         regs->fr[ 2] = 0LL;                             \
245         regs->fr[ 3] = 0LL;                             \
246         regs->gr[30] = ((current->mm->env_end)+63)&~63; \
247         regs->gr[31] = pc;                              \
248                                                         \
249         get_user(regs->gr[25],&sp[0]);                  \
250         regs->gr[24] = (unsigned long) &sp[1];          \
251         regs->gr[23] = 0;                               \
252                                                         \
253         regs->cr30 = (u32) current;                     \
254 } while(0)
255
256 #ifdef __LP64__
257
258 /*
259  * For 64 bit kernels we need a version of start thread for 32 bit
260  * elf files.
261  *
262  * FIXME: It should be possible to not duplicate the above code
263  *        by playing games with concatenation to form both
264  *        macros at compile time. The only difference between
265  *        this macro and the above is the name and the types
266  *        for sp and pc.
267  */
268
269 #define start_thread32(regs, new_pc, new_sp) do {         \
270         __u32 *sp = (__u32 *)new_sp;                    \
271         __u32 spaceid = (__u32)current->mm->context;    \
272         __u32 pc = (__u32)new_pc;                       \
273         /* offset pc for priv. level */                 \
274         pc |= 3;                                        \
275                                                         \
276         set_fs(USER_DS);                                \
277         regs->iasq[0] = spaceid;                        \
278         regs->iasq[1] = spaceid;                        \
279         regs->iaoq[0] = pc;                             \
280         regs->iaoq[1] = pc;                             \
281         regs->sr[2] = LINUX_GATEWAY_SPACE;              \
282         regs->sr[3] = 0xffff;                           \
283         regs->sr[4] = spaceid;                          \
284         regs->sr[5] = spaceid;                          \
285         regs->sr[6] = spaceid;                          \
286         regs->sr[7] = spaceid;                          \
287         regs->gr[ 0] = USER_INIT_PSW;                   \
288         regs->fr[ 0] = 0LL;                             \
289         regs->fr[ 1] = 0LL;                             \
290         regs->fr[ 2] = 0LL;                             \
291         regs->fr[ 3] = 0LL;                             \
292         regs->gr[30] = ((current->mm->env_end)+63)&~63; \
293         regs->gr[31] = pc;                              \
294                                                         \
295         get_user(regs->gr[25],&sp[0]);                  \
296         regs->gr[24] = (unsigned long) &sp[1];          \
297         regs->gr[23] = 0;                               \
298                                                         \
299         regs->cr30 = (u32) current;                     \
300 } while(0)
301
302 #endif
303
304 struct task_struct;
305
306 /* Free all resources held by a thread. */
307 extern void release_thread(struct task_struct *);
308 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
309
310 #define copy_segments(tsk, mm)  do { } while (0)
311 #define release_segments(mm)    do { } while (0)
312
313 extern inline unsigned long get_wchan(struct task_struct *p)
314 {
315         return 0xdeadbeef; /* XXX */
316 }
317
318 #define KSTK_EIP(tsk)   (0xdeadbeef)
319 #define KSTK_ESP(tsk)   (0xdeadbeef)
320
321 /* Be sure to hunt all references to this down when you change the size of
322  * the kernel stack */
323
324 #endif /* __ASSEMBLY__ */
325
326 #define THREAD_SIZE     (4*PAGE_SIZE)
327
328 #define alloc_task_struct() \
329         ((struct task_struct *) __get_free_pages(GFP_KERNEL,2))
330 #define free_task_struct(p)     free_pages((unsigned long)(p),2)
331 #define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
332
333 #define init_task (init_task_union.task) 
334 #define init_stack (init_task_union.stack)
335
336 #define cpu_relax()     do { } while (0)
337
338
339 #endif /* __ASM_PARISC_PROCESSOR_H */