OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-parisc/] [processor.h] - Blame information for rev 1779

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.