sched/headers: Prepare for new header dependencies before moving code to <linux/sched...
[linux-2.6-block.git] / arch / frv / kernel / process.c
CommitLineData
1da177e4
LT
1/* process.c: FRV specific parts of process handling
2 *
3 * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * - Derived from arch/m68k/kernel/process.c
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
9dec17eb 13#include <linux/module.h>
1da177e4
LT
14#include <linux/errno.h>
15#include <linux/sched.h>
b17b0153 16#include <linux/sched/debug.h>
1da177e4
LT
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/smp.h>
1da177e4
LT
20#include <linux/stddef.h>
21#include <linux/unistd.h>
22#include <linux/ptrace.h>
23#include <linux/slab.h>
24#include <linux/user.h>
25#include <linux/elf.h>
26#include <linux/reboot.h>
27#include <linux/interrupt.h>
8defab33 28#include <linux/pagemap.h>
41d8fe5b 29#include <linux/rcupdate.h>
1da177e4 30
84e8cd6d 31#include <asm/asm-offsets.h>
7c0f6ba6 32#include <linux/uaccess.h>
1da177e4
LT
33#include <asm/setup.h>
34#include <asm/pgtable.h>
8defab33 35#include <asm/tlb.h>
1da177e4
LT
36#include <asm/gdb-stub.h>
37#include <asm/mb-regs.h>
38
39#include "local.h"
40
41asmlinkage void ret_from_fork(void);
02ce496f 42asmlinkage void ret_from_kernel_thread(void);
1da177e4
LT
43
44#include <asm/pgalloc.h>
45
9dec17eb
DH
46void (*pm_power_off)(void);
47EXPORT_SYMBOL(pm_power_off);
48
1da177e4
LT
49static void core_sleep_idle(void)
50{
51#ifdef LED_DEBUG_SLEEP
52 /* Show that we're sleeping... */
53 __set_LEDS(0x55aa);
54#endif
55 frv_cpu_core_sleep();
56#ifdef LED_DEBUG_SLEEP
57 /* ... and that we woke up */
58 __set_LEDS(0);
59#endif
60 mb();
61}
62
ccf8e78f 63void arch_cpu_idle(void)
1da177e4 64{
ccf8e78f
TG
65 if (!frv_dma_inprogress)
66 core_sleep_idle();
67 else
68 local_irq_enable();
1da177e4
LT
69}
70
71void machine_restart(char * __unused)
72{
73 unsigned long reset_addr;
74#ifdef CONFIG_GDBSTUB
75 gdbstub_exit(0);
76#endif
77
78 if (PSR_IMPLE(__get_PSR()) == PSR_IMPLE_FR551)
79 reset_addr = 0xfefff500;
80 else
81 reset_addr = 0xfeff0500;
82
83 /* Software reset. */
84 asm volatile(" dcef @(gr0,gr0),1 ! membar !"
85 " sti %1,@(%0,0) !"
86 " nop ! nop ! nop ! nop ! nop ! "
87 " nop ! nop ! nop ! nop ! nop ! "
88 " nop ! nop ! nop ! nop ! nop ! "
89 " nop ! nop ! nop ! nop ! nop ! "
90 : : "r" (reset_addr), "r" (1) );
91
92 for (;;)
93 ;
94}
95
96void machine_halt(void)
97{
98#ifdef CONFIG_GDBSTUB
99 gdbstub_exit(0);
100#endif
101
102 for (;;);
103}
104
105void machine_power_off(void)
106{
107#ifdef CONFIG_GDBSTUB
108 gdbstub_exit(0);
109#endif
110
111 for (;;);
112}
113
114void flush_thread(void)
115{
adc400f6 116 /* nothing */
1da177e4
LT
117}
118
119inline unsigned long user_stack(const struct pt_regs *regs)
120{
121 while (regs->next_frame)
122 regs = regs->next_frame;
123 return user_mode(regs) ? regs->sp : 0;
124}
125
1da177e4
LT
126/*
127 * set up the kernel stack and exception frames for a new process
128 */
6f2c55b8 129int copy_thread(unsigned long clone_flags,
49ed3398 130 unsigned long usp, unsigned long arg,
afa86fc4 131 struct task_struct *p)
1da177e4 132{
02ce496f 133 struct pt_regs *childregs;
1da177e4 134
02ce496f 135 childregs = (struct pt_regs *)
84e8cd6d 136 (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
1da177e4 137
e7aa51b2 138 /* set up the userspace frame (the only place that the USP is stored) */
b9763ce3 139 *childregs = *current_pt_regs();
1da177e4
LT
140
141 p->thread.frame = childregs;
142 p->thread.curr = p;
143 p->thread.sp = (unsigned long) childregs;
144 p->thread.fp = 0;
145 p->thread.lr = 0;
02ce496f 146 p->thread.frame0 = childregs;
1da177e4 147
b9763ce3 148 if (unlikely(p->flags & PF_KTHREAD)) {
49ed3398
AV
149 childregs->gr9 = usp; /* function */
150 childregs->gr8 = arg;
49ed3398
AV
151 p->thread.pc = (unsigned long) ret_from_kernel_thread;
152 save_user_regs(p->thread.user);
153 return 0;
154 }
b9763ce3
AV
155 if (usp)
156 childregs->sp = usp;
49ed3398
AV
157 childregs->next_frame = NULL;
158
159 p->thread.pc = (unsigned long) ret_from_fork;
1da177e4
LT
160
161 /* the new TLS pointer is passed in as arg #5 to sys_clone() */
162 if (clone_flags & CLONE_SETTLS)
163 childregs->gr29 = childregs->gr12;
164
165 save_user_regs(p->thread.user);
166
167 return 0;
168} /* end copy_thread() */
169
1da177e4
LT
170unsigned long get_wchan(struct task_struct *p)
171{
172 struct pt_regs *regs0;
173 unsigned long fp, pc;
174 unsigned long stack_limit;
175 int count = 0;
176 if (!p || p == current || p->state == TASK_RUNNING)
177 return 0;
178
179 stack_limit = (unsigned long) (p + 1);
180 fp = p->thread.fp;
181 regs0 = p->thread.frame0;
182
183 do {
184 if (fp < stack_limit || fp >= (unsigned long) regs0 || fp & 3)
185 return 0;
186
187 pc = ((unsigned long *) fp)[2];
188
189 /* FIXME: This depends on the order of these functions. */
190 if (!in_sched_functions(pc))
191 return pc;
192
193 fp = *(unsigned long *) fp;
194 } while (count++ < 16);
195
196 return 0;
197}
198
199unsigned long thread_saved_pc(struct task_struct *tsk)
200{
201 /* Check whether the thread is blocked in resume() */
202 if (in_sched_functions(tsk->thread.pc))
203 return ((unsigned long *)tsk->thread.fp)[2];
204 else
205 return tsk->thread.pc;
206}
207
208int elf_check_arch(const struct elf32_hdr *hdr)
209{
210 unsigned long hsr0 = __get_HSR(0);
211 unsigned long psr = __get_PSR();
212
213 if (hdr->e_machine != EM_FRV)
214 return 0;
215
216 switch (hdr->e_flags & EF_FRV_GPR_MASK) {
217 case EF_FRV_GPR64:
218 if ((hsr0 & HSR0_GRN) == HSR0_GRN_32)
219 return 0;
220 case EF_FRV_GPR32:
221 case 0:
222 break;
223 default:
224 return 0;
225 }
226
227 switch (hdr->e_flags & EF_FRV_FPR_MASK) {
228 case EF_FRV_FPR64:
229 if ((hsr0 & HSR0_FRN) == HSR0_FRN_32)
230 return 0;
231 case EF_FRV_FPR32:
232 case EF_FRV_FPR_NONE:
233 case 0:
234 break;
235 default:
236 return 0;
237 }
238
239 if ((hdr->e_flags & EF_FRV_MULADD) == EF_FRV_MULADD)
240 if (PSR_IMPLE(psr) != PSR_IMPLE_FR405 &&
241 PSR_IMPLE(psr) != PSR_IMPLE_FR451)
242 return 0;
243
244 switch (hdr->e_flags & EF_FRV_CPU_MASK) {
245 case EF_FRV_CPU_GENERIC:
246 break;
247 case EF_FRV_CPU_FR300:
248 case EF_FRV_CPU_SIMPLE:
249 case EF_FRV_CPU_TOMCAT:
250 default:
251 return 0;
252 case EF_FRV_CPU_FR400:
253 if (PSR_IMPLE(psr) != PSR_IMPLE_FR401 &&
254 PSR_IMPLE(psr) != PSR_IMPLE_FR405 &&
255 PSR_IMPLE(psr) != PSR_IMPLE_FR451 &&
256 PSR_IMPLE(psr) != PSR_IMPLE_FR551)
257 return 0;
258 break;
259 case EF_FRV_CPU_FR450:
260 if (PSR_IMPLE(psr) != PSR_IMPLE_FR451)
261 return 0;
262 break;
263 case EF_FRV_CPU_FR500:
264 if (PSR_IMPLE(psr) != PSR_IMPLE_FR501)
265 return 0;
266 break;
267 case EF_FRV_CPU_FR550:
268 if (PSR_IMPLE(psr) != PSR_IMPLE_FR551)
269 return 0;
270 break;
271 }
272
273 return 1;
274}
6d8c4e3b
DH
275
276int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
277{
278 memcpy(fpregs,
279 &current->thread.user->f,
280 sizeof(current->thread.user->f));
281 return 1;
282}