2 * include/asm-parisc/processor.h
4 * Copyright (C) 1994 Linus Torvalds
5 * Copyright (C) 2001 Grant Grundler
8 #ifndef __ASM_PARISC_PROCESSOR_H
9 #define __ASM_PARISC_PROCESSOR_H
12 #include <linux/config.h>
13 #include <linux/threads.h>
15 #include <asm/hardware.h>
18 #include <asm/ptrace.h>
19 #include <asm/types.h>
20 #include <asm/system.h>
22 #include <asm/spinlock_t.h>
24 #endif /* __ASSEMBLY__ */
27 * Default implementation of macro that returns current
28 * instruction pointer ("program counter").
31 /* We cannot use MFIA as it was added for PA2.0 - prumpf
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. */
37 #define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; })
39 #define TASK_SIZE (current->thread.task_size)
40 #define DEFAULT_TASK_SIZE (0xFFF00000UL)
42 #define TASK_UNMAPPED_BASE (current->thread.map_base)
43 #define DEFAULT_MAP_BASE (0x40000000UL)
48 ** Data detected about CPUs at boot time which is the same for all CPU's.
49 ** HP boxes are SMP - ie identical processors.
51 ** FIXME: some CPU rev info may be processor specific...
53 struct system_cpuinfo_parisc {
54 unsigned int cpu_count;
56 unsigned int hversion;
57 unsigned int sversion;
58 enum cpu_type cpu_type;
61 struct pdc_model model;
62 unsigned long versions;
64 unsigned long capabilities;
65 char sys_model_name[81]; /* PDC-ROM returnes this model name */
68 char *cpu_name; /* e.g. "PA7300LC (PCX-L2)" */
69 char *family_name; /* e.g. "1.1e" */
74 ** Per CPU data structure - ie varies per CPU.
76 struct cpuinfo_parisc {
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 */
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 */
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 */
94 unsigned long fp_model;
96 struct parisc_device *dev;
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()]
103 #define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
112 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
118 struct thread_struct {
120 unsigned long task_size;
121 unsigned long map_base;
125 /* Thread struct flags. */
126 #define PARISC_KERNEL_DEATH (1UL << 31) /* see die_if_kernel()... */
128 #define INIT_THREAD { \
129 regs: { gr: { 0, }, \
136 task_size: DEFAULT_TASK_SIZE, \
137 map_base: DEFAULT_MAP_BASE, \
142 * Return saved PC of a blocked thread. This is used by ps mostly.
145 static inline unsigned long thread_saved_pc(struct thread_struct *t)
151 * Start user thread in another space.
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.
159 * For ELF we clear r23, because the dynamic linker uses it to pass
160 * the address of the finalizer function.
162 * We also initialize sr3 to an illegal value (illegal for our
163 * implementation, not for the architecture).
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 */ \
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; \
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]); \
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.
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.
202 * Duplicated from dl-machine.h for the benefit of readers:
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
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 |
215 |---------------------------------|
217 |---------------------------------|
218 | Environment pointers |
219 |---------------------------------|
221 |---------------------------------|
222 | Argument pointers |
223 |---------------------------------| <- argv
225 |---------------------------------| <- bprm->exec (HACK!)
227 |---------------------------------|
228 | filename passed to execve |
229 |---------------------------------| (mm->env_end)
231 |---------------------------------| (mm->env_start, mm->arg_end)
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.
239 on downward growing arches, it looks like this:
240 stack base at TASK_SIZE
241 | filename passed to execve
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
256 * Note that the S/390 people took the easy way out and hacked their
257 * GCC to make the stack grow downwards.
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; \
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; \
285 get_user(regs->gr[25], (argv - 1)); \
286 regs->gr[24] = (long) argv; \
293 /* Free all resources held by a thread. */
294 extern void release_thread(struct task_struct *);
295 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
297 extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
299 #define copy_segments(tsk, mm) do { \
300 if (tsk->personality == PER_HPUX) \
301 map_hpux_gateway_page(tsk,mm); \
303 #define release_segments(mm) do { } while (0)
305 static inline unsigned long get_wchan(struct task_struct *p)
307 return 0xdeadbeef; /* XXX */
310 #define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0])
311 #define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30])
313 #endif /* __ASSEMBLY__ */
316 #define ARCH_HAS_PREFETCH
317 extern inline void prefetch(const void *addr)
319 __asm__("ldw 0(%0), %%r0" : : "r" (addr));
322 #define ARCH_HAS_PREFETCHW
323 extern inline void prefetchw(const void *addr)
325 __asm__("ldd 0(%0), %%r0" : : "r" (addr));
329 /* Be sure to hunt all references to this down when you change the size of
330 * the kernel stack */
332 #define THREAD_SIZE (4*PAGE_SIZE)
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)
339 #define init_task (init_task_union.task)
340 #define init_stack (init_task_union.stack)
342 #define cpu_relax() do { } while (0)
344 #endif /* __ASM_PARISC_PROCESSOR_H */