diff options
Diffstat (limited to 'arch/sh64')
-rw-r--r-- | arch/sh64/kernel/process.c | 270 |
1 files changed, 13 insertions, 257 deletions
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index db475b7833fb..525d0ec19b78 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c | |||
@@ -20,261 +20,16 @@ | |||
20 | /* | 20 | /* |
21 | * This file handles the architecture-dependent parts of process handling.. | 21 | * This file handles the architecture-dependent parts of process handling.. |
22 | */ | 22 | */ |
23 | |||
24 | /* Temporary flags/tests. All to be removed/undefined. BEGIN */ | ||
25 | #define IDLE_TRACE | ||
26 | #define VM_SHOW_TABLES | ||
27 | #define VM_TEST_FAULT | ||
28 | #define VM_TEST_RTLBMISS | ||
29 | #define VM_TEST_WTLBMISS | ||
30 | |||
31 | #undef VM_SHOW_TABLES | ||
32 | #undef IDLE_TRACE | ||
33 | /* Temporary flags/tests. All to be removed/undefined. END */ | ||
34 | |||
35 | #define __KERNEL_SYSCALLS__ | ||
36 | #include <stdarg.h> | ||
37 | |||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/rwsem.h> | ||
40 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
41 | #include <linux/smp.h> | ||
42 | #include <linux/smp_lock.h> | ||
43 | #include <linux/ptrace.h> | 24 | #include <linux/ptrace.h> |
44 | #include <linux/slab.h> | ||
45 | #include <linux/vmalloc.h> | ||
46 | #include <linux/user.h> | ||
47 | #include <linux/a.out.h> | ||
48 | #include <linux/interrupt.h> | ||
49 | #include <linux/unistd.h> | ||
50 | #include <linux/delay.h> | ||
51 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
52 | #include <linux/init.h> | 26 | #include <linux/init.h> |
53 | 27 | #include <linux/module.h> | |
54 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
55 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
56 | #include <asm/system.h> | ||
57 | #include <asm/io.h> | ||
58 | #include <asm/processor.h> /* includes also <asm/registers.h> */ | ||
59 | #include <asm/mmu_context.h> | ||
60 | #include <asm/elf.h> | ||
61 | #include <asm/page.h> | ||
62 | |||
63 | #include <linux/irq.h> | ||
64 | 30 | ||
65 | struct task_struct *last_task_used_math = NULL; | 31 | struct task_struct *last_task_used_math = NULL; |
66 | 32 | ||
67 | #ifdef IDLE_TRACE | ||
68 | #ifdef VM_SHOW_TABLES | ||
69 | /* For testing */ | ||
70 | static void print_PTE(long base) | ||
71 | { | ||
72 | int i, skip=0; | ||
73 | long long x, y, *p = (long long *) base; | ||
74 | |||
75 | for (i=0; i< 512; i++, p++){ | ||
76 | if (*p == 0) { | ||
77 | if (!skip) { | ||
78 | skip++; | ||
79 | printk("(0s) "); | ||
80 | } | ||
81 | } else { | ||
82 | skip=0; | ||
83 | x = (*p) >> 32; | ||
84 | y = (*p) & 0xffffffff; | ||
85 | printk("%08Lx%08Lx ", x, y); | ||
86 | if (!((i+1)&0x3)) printk("\n"); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* For testing */ | ||
92 | static void print_DIR(long base) | ||
93 | { | ||
94 | int i, skip=0; | ||
95 | long *p = (long *) base; | ||
96 | |||
97 | for (i=0; i< 512; i++, p++){ | ||
98 | if (*p == 0) { | ||
99 | if (!skip) { | ||
100 | skip++; | ||
101 | printk("(0s) "); | ||
102 | } | ||
103 | } else { | ||
104 | skip=0; | ||
105 | printk("%08lx ", *p); | ||
106 | if (!((i+1)&0x7)) printk("\n"); | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /* For testing */ | ||
112 | static void print_vmalloc_first_tables(void) | ||
113 | { | ||
114 | |||
115 | #define PRESENT 0x800 /* Bit 11 */ | ||
116 | |||
117 | /* | ||
118 | * Do it really dirty by looking at raw addresses, | ||
119 | * raw offsets, no types. If we used pgtable/pgalloc | ||
120 | * macros/definitions we could hide potential bugs. | ||
121 | * | ||
122 | * Note that pointers are 32-bit for CDC. | ||
123 | */ | ||
124 | long pgdt, pmdt, ptet; | ||
125 | |||
126 | pgdt = (long) &swapper_pg_dir; | ||
127 | printk("-->PGD (0x%08lx):\n", pgdt); | ||
128 | print_DIR(pgdt); | ||
129 | printk("\n"); | ||
130 | |||
131 | /* VMALLOC pool is mapped at 0xc0000000, second (pointer) entry in PGD */ | ||
132 | pgdt += 4; | ||
133 | pmdt = (long) (* (long *) pgdt); | ||
134 | if (!(pmdt & PRESENT)) { | ||
135 | printk("No PMD\n"); | ||
136 | return; | ||
137 | } else pmdt &= 0xfffff000; | ||
138 | |||
139 | printk("-->PMD (0x%08lx):\n", pmdt); | ||
140 | print_DIR(pmdt); | ||
141 | printk("\n"); | ||
142 | |||
143 | /* Get the pmdt displacement for 0xc0000000 */ | ||
144 | pmdt += 2048; | ||
145 | |||
146 | /* just look at first two address ranges ... */ | ||
147 | /* ... 0xc0000000 ... */ | ||
148 | ptet = (long) (* (long *) pmdt); | ||
149 | if (!(ptet & PRESENT)) { | ||
150 | printk("No PTE0\n"); | ||
151 | return; | ||
152 | } else ptet &= 0xfffff000; | ||
153 | |||
154 | printk("-->PTE0 (0x%08lx):\n", ptet); | ||
155 | print_PTE(ptet); | ||
156 | printk("\n"); | ||
157 | |||
158 | /* ... 0xc0001000 ... */ | ||
159 | ptet += 4; | ||
160 | if (!(ptet & PRESENT)) { | ||
161 | printk("No PTE1\n"); | ||
162 | return; | ||
163 | } else ptet &= 0xfffff000; | ||
164 | printk("-->PTE1 (0x%08lx):\n", ptet); | ||
165 | print_PTE(ptet); | ||
166 | printk("\n"); | ||
167 | } | ||
168 | #else | ||
169 | #define print_vmalloc_first_tables() | ||
170 | #endif /* VM_SHOW_TABLES */ | ||
171 | |||
172 | static void test_VM(void) | ||
173 | { | ||
174 | void *a, *b, *c; | ||
175 | |||
176 | #ifdef VM_SHOW_TABLES | ||
177 | printk("Initial PGD/PMD/PTE\n"); | ||
178 | #endif | ||
179 | print_vmalloc_first_tables(); | ||
180 | |||
181 | printk("Allocating 2 bytes\n"); | ||
182 | a = vmalloc(2); | ||
183 | print_vmalloc_first_tables(); | ||
184 | |||
185 | printk("Allocating 4100 bytes\n"); | ||
186 | b = vmalloc(4100); | ||
187 | print_vmalloc_first_tables(); | ||
188 | |||
189 | printk("Allocating 20234 bytes\n"); | ||
190 | c = vmalloc(20234); | ||
191 | print_vmalloc_first_tables(); | ||
192 | |||
193 | #ifdef VM_TEST_FAULT | ||
194 | /* Here you may want to fault ! */ | ||
195 | |||
196 | #ifdef VM_TEST_RTLBMISS | ||
197 | printk("Ready to fault upon read.\n"); | ||
198 | if (* (char *) a) { | ||
199 | printk("RTLBMISSed on area a !\n"); | ||
200 | } | ||
201 | printk("RTLBMISSed on area a !\n"); | ||
202 | #endif | ||
203 | |||
204 | #ifdef VM_TEST_WTLBMISS | ||
205 | printk("Ready to fault upon write.\n"); | ||
206 | *((char *) b) = 'L'; | ||
207 | printk("WTLBMISSed on area b !\n"); | ||
208 | #endif | ||
209 | |||
210 | #endif /* VM_TEST_FAULT */ | ||
211 | |||
212 | printk("Deallocating the 4100 byte chunk\n"); | ||
213 | vfree(b); | ||
214 | print_vmalloc_first_tables(); | ||
215 | |||
216 | printk("Deallocating the 2 byte chunk\n"); | ||
217 | vfree(a); | ||
218 | print_vmalloc_first_tables(); | ||
219 | |||
220 | printk("Deallocating the last chunk\n"); | ||
221 | vfree(c); | ||
222 | print_vmalloc_first_tables(); | ||
223 | } | ||
224 | |||
225 | extern unsigned long volatile jiffies; | ||
226 | int once = 0; | ||
227 | unsigned long old_jiffies; | ||
228 | int pid = -1, pgid = -1; | ||
229 | |||
230 | void idle_trace(void) | ||
231 | { | ||
232 | |||
233 | _syscall0(int, getpid) | ||
234 | _syscall1(int, getpgid, int, pid) | ||
235 | |||
236 | if (!once) { | ||
237 | /* VM allocation/deallocation simple test */ | ||
238 | test_VM(); | ||
239 | pid = getpid(); | ||
240 | |||
241 | printk("Got all through to Idle !!\n"); | ||
242 | printk("I'm now going to loop forever ...\n"); | ||
243 | printk("Any ! below is a timer tick.\n"); | ||
244 | printk("Any . below is a getpgid system call from pid = %d.\n", pid); | ||
245 | |||
246 | |||
247 | old_jiffies = jiffies; | ||
248 | once++; | ||
249 | } | ||
250 | |||
251 | if (old_jiffies != jiffies) { | ||
252 | old_jiffies = jiffies - old_jiffies; | ||
253 | switch (old_jiffies) { | ||
254 | case 1: | ||
255 | printk("!"); | ||
256 | break; | ||
257 | case 2: | ||
258 | printk("!!"); | ||
259 | break; | ||
260 | case 3: | ||
261 | printk("!!!"); | ||
262 | break; | ||
263 | case 4: | ||
264 | printk("!!!!"); | ||
265 | break; | ||
266 | default: | ||
267 | printk("(%d!)", (int) old_jiffies); | ||
268 | } | ||
269 | old_jiffies = jiffies; | ||
270 | } | ||
271 | pgid = getpgid(pid); | ||
272 | printk("."); | ||
273 | } | ||
274 | #else | ||
275 | #define idle_trace() do { } while (0) | ||
276 | #endif /* IDLE_TRACE */ | ||
277 | |||
278 | static int hlt_counter = 1; | 33 | static int hlt_counter = 1; |
279 | 34 | ||
280 | #define HARD_IDLE_TIMEOUT (HZ / 3) | 35 | #define HARD_IDLE_TIMEOUT (HZ / 3) |
@@ -323,7 +78,6 @@ void cpu_idle(void) | |||
323 | local_irq_disable(); | 78 | local_irq_disable(); |
324 | while (!need_resched()) { | 79 | while (!need_resched()) { |
325 | local_irq_enable(); | 80 | local_irq_enable(); |
326 | idle_trace(); | ||
327 | hlt(); | 81 | hlt(); |
328 | local_irq_disable(); | 82 | local_irq_disable(); |
329 | } | 83 | } |
@@ -622,6 +376,10 @@ void free_task_struct(struct task_struct *p) | |||
622 | /* | 376 | /* |
623 | * Create a kernel thread | 377 | * Create a kernel thread |
624 | */ | 378 | */ |
379 | ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
380 | { | ||
381 | do_exit(fn(arg)); | ||
382 | } | ||
625 | 383 | ||
626 | /* | 384 | /* |
627 | * This is the mechanism for creating a new kernel thread. | 385 | * This is the mechanism for creating a new kernel thread. |
@@ -633,19 +391,17 @@ void free_task_struct(struct task_struct *p) | |||
633 | */ | 391 | */ |
634 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | 392 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) |
635 | { | 393 | { |
636 | /* A bit less processor dependent than older sh ... */ | 394 | struct pt_regs regs; |
637 | unsigned int reply; | ||
638 | 395 | ||
639 | static __inline__ _syscall2(int,clone,unsigned long,flags,unsigned long,newsp) | 396 | memset(®s, 0, sizeof(regs)); |
640 | static __inline__ _syscall1(int,exit,int,ret) | 397 | regs.regs[2] = (unsigned long)arg; |
398 | regs.regs[3] = (unsigned long)fn; | ||
641 | 399 | ||
642 | reply = clone(flags | CLONE_VM, 0); | 400 | regs.pc = (unsigned long)kernel_thread_helper; |
643 | if (!reply) { | 401 | regs.sr = (1 << 30); |
644 | /* Child */ | ||
645 | reply = exit(fn(arg)); | ||
646 | } | ||
647 | 402 | ||
648 | return reply; | 403 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, |
404 | ®s, 0, NULL, NULL); | ||
649 | } | 405 | } |
650 | 406 | ||
651 | /* | 407 | /* |