File: /usr/src/linux/include/asm-sparc/processor.h

1     /* $Id: processor.h,v 1.82 2001/09/20 00:35:34 davem Exp $
2      * include/asm-sparc/processor.h
3      *
4      * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
5      */
6     
7     #ifndef __ASM_SPARC_PROCESSOR_H
8     #define __ASM_SPARC_PROCESSOR_H
9     
10     /*
11      * Sparc32 implementation of macro that returns current
12      * instruction pointer ("program counter").
13      */
14     #define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
15     
16     #include <linux/a.out.h>
17     
18     #include <asm/psr.h>
19     #include <asm/ptrace.h>
20     #include <asm/head.h>
21     #include <asm/signal.h>
22     #include <asm/segment.h>
23     #include <asm/btfixup.h>
24     #include <asm/page.h>
25     #include <asm/atomic.h>
26     
27     /*
28      * Bus types
29      */
30     #define EISA_bus 0
31     #define EISA_bus__is_a_macro /* for versions in ksyms.c */
32     #define MCA_bus 0
33     #define MCA_bus__is_a_macro /* for versions in ksyms.c */
34     
35     /*
36      * The sparc has no problems with write protection
37      */
38     #define wp_works_ok 1
39     #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
40     
41     /* Whee, this is STACK_TOP + PAGE_SIZE and the lowest kernel address too... 
42      * That one page is used to protect kernel from intruders, so that
43      * we can make our access_ok test faster
44      */
45     #define TASK_SIZE	PAGE_OFFSET
46     
47     struct fpq {
48     	unsigned long *insn_addr;
49     	unsigned long insn;
50     };
51     
52     typedef struct {
53     	int seg;
54     } mm_segment_t;
55     
56     /* The Sparc processor specific thread struct. */
57     struct thread_struct {
58     	unsigned long uwinmask __attribute__ ((aligned (8)));
59     	struct pt_regs *kregs;
60     
61     	/* Context switch saved kernel state. */
62     	unsigned long ksp __attribute__ ((aligned (8)));
63     	unsigned long kpc;
64     	unsigned long kpsr;
65     	unsigned long kwim;
66     
67     	/* Special child fork kpsr/kwim values. */
68     	unsigned long fork_kpsr __attribute__ ((aligned (8)));
69     	unsigned long fork_kwim;
70     
71     	/* A place to store user windows and stack pointers
72     	 * when the stack needs inspection.
73     	 */
74     #define NSWINS 8
75     	struct reg_window reg_window[NSWINS] __attribute__ ((aligned (8)));
76     	unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
77     	unsigned long w_saved;
78     
79     	/* Floating point regs */
80     	unsigned long   float_regs[32] __attribute__ ((aligned (8)));
81     	unsigned long   fsr;
82     	unsigned long   fpqdepth;
83     	struct fpq	fpqueue[16];
84     	unsigned long flags;
85     	mm_segment_t current_ds;
86     	struct exec core_exec;     /* just what it says. */
87     	int new_signal;
88     	atomic_t refcount;	/* used for sun4c only */
89     };
90     
91     #define SPARC_FLAG_KTHREAD      0x1    /* task is a kernel thread */
92     #define SPARC_FLAG_UNALIGNED    0x2    /* is allowed to do unaligned accesses */
93     
94     #define INIT_THREAD  { \
95     /* uwinmask, kregs, ksp, kpc, kpsr, kwim */ \
96        0,        0,     0,   0,   0,    0, \
97     /* fork_kpsr, fork_kwim */ \
98        0,         0, \
99     /* reg_window */  \
100     { { { 0, }, { 0, } }, }, \
101     /* rwbuf_stkptrs */  \
102     { 0, 0, 0, 0, 0, 0, 0, 0, }, \
103     /* w_saved */ \
104        0, \
105     /* FPU regs */   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
106                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
107     /* FPU status, FPU qdepth, FPU queue */ \
108        0,          0,  { { 0, 0, }, }, \
109     /* flags,              current_ds, */ \
110        SPARC_FLAG_KTHREAD, KERNEL_DS, \
111     /* core_exec */ \
112     { 0, }, \
113     /* new_signal */ \
114       0, \
115     }
116     
117     /* Return saved PC of a blocked thread. */
118     extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
119     {
120     	return t->kpc;
121     }
122     
123     /* Do necessary setup to start up a newly executed thread. */
124     extern __inline__ void start_thread(struct pt_regs * regs, unsigned long pc,
125     				    unsigned long sp)
126     {
127     	register unsigned long zero asm("g1");
128     
129     	regs->psr = (regs->psr & (PSR_CWP)) | PSR_S;
130     	regs->pc = ((pc & (~3)) - 4);
131     	regs->npc = regs->pc + 4;
132     	regs->y = 0;
133     	zero = 0;
134     	__asm__ __volatile__("std\t%%g0, [%0 + %3 + 0x00]\n\t"
135     			     "std\t%%g0, [%0 + %3 + 0x08]\n\t"
136     			     "std\t%%g0, [%0 + %3 + 0x10]\n\t"
137     			     "std\t%%g0, [%0 + %3 + 0x18]\n\t"
138     			     "std\t%%g0, [%0 + %3 + 0x20]\n\t"
139     			     "std\t%%g0, [%0 + %3 + 0x28]\n\t"
140     			     "std\t%%g0, [%0 + %3 + 0x30]\n\t"
141     			     "st\t%1, [%0 + %3 + 0x38]\n\t"
142     			     "st\t%%g0, [%0 + %3 + 0x3c]"
143     			     : : "r" (regs), "r" (sp - REGWIN_SZ), "r" (zero),
144     			     "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0])));
145     }
146     
147     /* Free all resources held by a thread. */
148     #define release_thread(tsk)		do { } while(0)
149     extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
150     
151     
152     #define copy_segments(tsk, mm)		do { } while (0)
153     #define release_segments(mm)		do { } while (0)
154     
155     #define get_wchan(__TSK) \
156     ({	extern void scheduling_functions_start_here(void); \
157     	extern void scheduling_functions_end_here(void); \
158     	unsigned long pc, fp, bias = 0; \
159     	unsigned long task_base = (unsigned long) (__TSK); \
160             unsigned long __ret = 0; \
161     	struct reg_window *rw; \
162     	int count = 0; \
163     	if (!(__TSK) || (__TSK) == current || \
164                 (__TSK)->state == TASK_RUNNING) \
165     		goto __out; \
166     	fp = (__TSK)->thread.ksp + bias; \
167     	do { \
168     		/* Bogus frame pointer? */ \
169     		if (fp < (task_base + sizeof(struct task_struct)) || \
170     		    fp >= (task_base + (2 * PAGE_SIZE))) \
171     			break; \
172     		rw = (struct reg_window *) fp; \
173     		pc = rw->ins[7]; \
174     		if (pc < ((unsigned long) scheduling_functions_start_here) || \
175                         pc >= ((unsigned long) scheduling_functions_end_here)) { \
176     			__ret = pc; \
177     			goto __out; \
178     		} \
179     		fp = rw->ins[6] + bias; \
180     	} while (++count < 16); \
181     __out:	__ret; \
182     })
183     
184     #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
185     #define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
186     
187     #ifdef __KERNEL__
188     #define THREAD_SIZE (2*PAGE_SIZE)
189     
190     extern struct task_struct *last_task_used_math;
191     
192     /* Allocation and freeing of basic task resources. */
193     BTFIXUPDEF_CALL(struct task_struct *, alloc_task_struct, void)
194     BTFIXUPDEF_CALL(void, free_task_struct, struct task_struct *)
195     BTFIXUPDEF_CALL(void, get_task_struct, struct task_struct *)
196     
197     #define alloc_task_struct() BTFIXUP_CALL(alloc_task_struct)()
198     #define free_task_struct(tsk) BTFIXUP_CALL(free_task_struct)(tsk)
199     #define get_task_struct(tsk) BTFIXUP_CALL(get_task_struct)(tsk)
200     
201     #define init_task	(init_task_union.task)
202     #define init_stack	(init_task_union.stack)
203     
204     #endif
205     
206     #endif /* __ASM_SPARC_PROCESSOR_H */
207