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

1     /* $Id: processor.h,v 1.75 2001/09/20 00:35:34 davem Exp $
2      * include/asm-sparc64/processor.h
3      *
4      * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5      */
6     
7     #ifndef __ASM_SPARC64_PROCESSOR_H
8     #define __ASM_SPARC64_PROCESSOR_H
9     
10     /*
11      * Sparc64 implementation of macro that returns current
12      * instruction pointer ("program counter").
13      */
14     #define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
15     
16     #include <linux/config.h>
17     #include <asm/asi.h>
18     #include <asm/a.out.h>
19     #include <asm/pstate.h>
20     #include <asm/ptrace.h>
21     #include <asm/signal.h>
22     #include <asm/segment.h>
23     #include <asm/page.h>
24     
25     /* Bus types */
26     #define EISA_bus 0
27     #define EISA_bus__is_a_macro /* for versions in ksyms.c */
28     #define MCA_bus 0
29     #define MCA_bus__is_a_macro /* for versions in ksyms.c */
30     
31     /* The sparc has no problems with write protection */
32     #define wp_works_ok 1
33     #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
34     
35     /*
36      * User lives in his very own context, and cannot reference us. Note
37      * that TASK_SIZE is a misnomer, it really gives maximum user virtual 
38      * address that the kernel will allocate out.
39      */
40     #define VA_BITS		44
41     #define VPTE_SIZE	(1UL << (VA_BITS - PAGE_SHIFT + 3))
42     #define TASK_SIZE	((unsigned long)-VPTE_SIZE)
43     
44     #ifndef __ASSEMBLY__
45     
46     #define NSWINS		7
47     
48     typedef struct {
49     	unsigned char seg;
50     } mm_segment_t;
51     
52     /* The Sparc processor specific thread struct. */
53     struct thread_struct {
54     	/* D$ line 1 */
55     	unsigned long ksp __attribute__ ((aligned(16)));
56     	unsigned char wstate, cwp, flags;
57     	mm_segment_t current_ds;
58     	unsigned char w_saved, fpdepth, fault_code, use_blkcommit;
59     	unsigned long fault_address;
60     	unsigned char fpsaved[7];
61     	unsigned char __pad2;
62     	
63     	/* D$ line 2, 3, 4 */
64     	struct pt_regs *kregs;
65     	unsigned long *utraps;
66     	unsigned long gsr[7];
67     	unsigned long xfsr[7];
68     
69     	struct reg_window reg_window[NSWINS];
70     	unsigned long rwbuf_stkptrs[NSWINS];
71     	
72     	/* Performance counter state */
73     	u64 *user_cntd0, *user_cntd1;
74     	u64 kernel_cntd0, kernel_cntd1;
75     	u64 pcr_reg;
76     };
77     
78     #endif /* !(__ASSEMBLY__) */
79     
80     #define SPARC_FLAG_UNALIGNED    0x01    /* is allowed to do unaligned accesses	*/
81     #define SPARC_FLAG_NEWSIGNALS   0x02    /* task wants new-style signals		*/
82     #define SPARC_FLAG_32BIT        0x04    /* task is older 32-bit binary		*/
83     #define SPARC_FLAG_NEWCHILD     0x08    /* task is just-spawned child process	*/
84     #define SPARC_FLAG_PERFCTR	0x10    /* task has performance counters active	*/
85     
86     #define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB		*/
87     #define FAULT_CODE_DTLB		0x02	/* Miss happened in D-TLB		*/
88     #define FAULT_CODE_ITLB		0x04	/* Miss happened in I-TLB		*/
89     #define FAULT_CODE_WINFIXUP	0x08	/* Miss happened during spill/fill	*/
90     
91     #define INIT_THREAD  {					\
92     /* ksp, wstate, cwp, flags, current_ds, */ 		\
93        0,   0,      0,   0,     KERNEL_DS,			\
94     /* w_saved, fpdepth, fault_code, use_blkcommit, */	\
95        0,       0,       0,          0,			\
96     /* fault_address, fpsaved, __pad2, kregs, */		\
97        0,             { 0 },   0,      0,			\
98     /* utraps, gsr,   xfsr, */				\
99        0,	   { 0 }, { 0 },				\
100     /* reg_window */					\
101        { { { 0, }, { 0, } }, }, 				\
102     /* rwbuf_stkptrs */					\
103        { 0, 0, 0, 0, 0, 0, 0, },				\
104     /* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \
105        0,          0,          0,		 0,            0, \
106     }
107     
108     #ifdef __KERNEL__
109     #if PAGE_SHIFT == 13
110     #define THREAD_SIZE (2*PAGE_SIZE)
111     #define THREAD_SHIFT (PAGE_SHIFT + 1)
112     #else /* PAGE_SHIFT == 13 */
113     #define THREAD_SIZE PAGE_SIZE
114     #define THREAD_SHIFT PAGE_SHIFT
115     #endif /* PAGE_SHIFT == 13 */
116     #endif /* __KERNEL__ */
117     
118     #ifndef __ASSEMBLY__
119     
120     /* Return saved PC of a blocked thread. */
121     extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
122     {
123     	unsigned long ret = 0xdeadbeefUL;
124     	
125     	if (t->ksp) {
126     		unsigned long *sp;
127     		sp = (unsigned long *)(t->ksp + STACK_BIAS);
128     		if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
129     		    sp[14]) {
130     			unsigned long *fp;
131     			fp = (unsigned long *)(sp[14] + STACK_BIAS);
132     			if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
133     				ret = fp[15];
134     		}
135     	}
136     	return ret;
137     }
138     
139     /* On Uniprocessor, even in RMO processes see TSO semantics */
140     #ifdef CONFIG_SMP
141     #define TSTATE_INITIAL_MM	TSTATE_TSO
142     #else
143     #define TSTATE_INITIAL_MM	TSTATE_RMO
144     #endif
145     
146     /* Do necessary setup to start up a newly executed thread. */
147     #define start_thread(regs, pc, sp) \
148     do { \
149     	regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (ASI_PNF << 24); \
150     	regs->tpc = ((pc & (~3)) - 4); \
151     	regs->tnpc = regs->tpc + 4; \
152     	regs->y = 0; \
153     	current->thread.wstate = (1 << 3); \
154     	if (current->thread.utraps) { \
155     		if (*(current->thread.utraps) < 2) \
156     			kfree (current->thread.utraps); \
157     		else \
158     			(*(current->thread.utraps))--; \
159     		current->thread.utraps = NULL; \
160     	} \
161     	__asm__ __volatile__( \
162     	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
163     	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
164     	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
165     	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
166     	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
167     	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
168     	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
169     	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
170     	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
171     	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
172     	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
173     	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
174     	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
175     	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
176     	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
177     	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
178     	"wrpr		%%g0, (1 << 3), %%wstate\n\t" \
179     	: \
180     	: "r" (regs), "r" (sp - REGWIN_SZ - STACK_BIAS), \
181     	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
182     } while(0)
183     
184     #define start_thread32(regs, pc, sp) \
185     do { \
186     	pc &= 0x00000000ffffffffUL; \
187     	sp &= 0x00000000ffffffffUL; \
188     \
189     	regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM); \
190     	regs->tpc = ((pc & (~3)) - 4); \
191     	regs->tnpc = regs->tpc + 4; \
192     	regs->y = 0; \
193     	current->thread.wstate = (2 << 3); \
194     	if (current->thread.utraps) { \
195     		if (*(current->thread.utraps) < 2) \
196     			kfree (current->thread.utraps); \
197     		else \
198     			(*(current->thread.utraps))--; \
199     		current->thread.utraps = NULL; \
200     	} \
201     	__asm__ __volatile__( \
202     	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
203     	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
204     	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
205     	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
206     	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
207     	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
208     	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
209     	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
210     	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
211     	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
212     	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
213     	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
214     	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
215     	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
216     	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
217     	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
218     	"wrpr		%%g0, (2 << 3), %%wstate\n\t" \
219     	: \
220     	: "r" (regs), "r" (sp - REGWIN32_SZ), \
221     	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
222     } while(0)
223     
224     /* Free all resources held by a thread. */
225     #define release_thread(tsk)		do { } while(0)
226     
227     extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
228     
229     #define copy_segments(tsk, mm)		do { } while (0)
230     #define release_segments(mm)		do { } while (0)
231     
232     #define get_wchan(__TSK) \
233     ({	extern void scheduling_functions_start_here(void); \
234     	extern void scheduling_functions_end_here(void); \
235     	unsigned long pc, fp, bias = 0; \
236     	unsigned long task_base = (unsigned long) (__TSK); \
237     	struct reg_window *rw; \
238             unsigned long __ret = 0; \
239     	int count = 0; \
240     	if (!(__TSK) || (__TSK) == current || \
241                 (__TSK)->state == TASK_RUNNING) \
242     		goto __out; \
243     	bias = STACK_BIAS; \
244     	fp = (__TSK)->thread.ksp + bias; \
245     	do { \
246     		/* Bogus frame pointer? */ \
247     		if (fp < (task_base + sizeof(struct task_struct)) || \
248     		    fp >= (task_base + THREAD_SIZE)) \
249     			break; \
250     		rw = (struct reg_window *) fp; \
251     		pc = rw->ins[7]; \
252     		if (pc < ((unsigned long) scheduling_functions_start_here) || \
253     		    pc >= ((unsigned long) scheduling_functions_end_here)) { \
254     			__ret = pc; \
255     			goto __out; \
256     		} \
257     		fp = rw->ins[6] + bias; \
258     	} while (++count < 16); \
259     __out:	__ret; \
260     })
261     
262     #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
263     #define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
264     
265     #ifdef __KERNEL__
266     /* Allocation and freeing of task_struct and kernel stack. */
267     #if PAGE_SHIFT == 13
268     #define alloc_task_struct()   ((struct task_struct *)__get_free_pages(GFP_KERNEL, 1))
269     #define free_task_struct(tsk) free_pages((unsigned long)(tsk),1)
270     #else /* PAGE_SHIFT == 13 */
271     #define alloc_task_struct()   ((struct task_struct *)__get_free_pages(GFP_KERNEL, 0))
272     #define free_task_struct(tsk) free_pages((unsigned long)(tsk),0)
273     #endif /* PAGE_SHIFT == 13 */
274     #define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
275     
276     #define init_task	(init_task_union.task)
277     #define init_stack	(init_task_union.stack)
278     
279     #endif /* __KERNEL__ */
280     
281     #endif /* !(__ASSEMBLY__) */
282     
283     #endif /* !(__ASM_SPARC64_PROCESSOR_H) */
284