Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.23-rc2 695 lines 19 kB view raw
1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * arch/sh64/kernel/process.c 7 * 8 * Copyright (C) 2000, 2001 Paolo Alberelli 9 * Copyright (C) 2003 Paul Mundt 10 * Copyright (C) 2003, 2004 Richard Curnow 11 * 12 * Started from SH3/4 version: 13 * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima 14 * 15 * In turn started from i386 version: 16 * Copyright (C) 1995 Linus Torvalds 17 * 18 */ 19 20/* 21 * This file handles the architecture-dependent parts of process handling.. 22 */ 23#include <linux/mm.h> 24#include <linux/fs.h> 25#include <linux/ptrace.h> 26#include <linux/reboot.h> 27#include <linux/init.h> 28#include <linux/module.h> 29#include <asm/uaccess.h> 30#include <asm/pgtable.h> 31 32struct task_struct *last_task_used_math = NULL; 33 34static int hlt_counter = 1; 35 36#define HARD_IDLE_TIMEOUT (HZ / 3) 37 38void disable_hlt(void) 39{ 40 hlt_counter++; 41} 42 43void enable_hlt(void) 44{ 45 hlt_counter--; 46} 47 48static int __init nohlt_setup(char *__unused) 49{ 50 hlt_counter = 1; 51 return 1; 52} 53 54static int __init hlt_setup(char *__unused) 55{ 56 hlt_counter = 0; 57 return 1; 58} 59 60__setup("nohlt", nohlt_setup); 61__setup("hlt", hlt_setup); 62 63static inline void hlt(void) 64{ 65 __asm__ __volatile__ ("sleep" : : : "memory"); 66} 67 68/* 69 * The idle loop on a uniprocessor SH.. 70 */ 71void cpu_idle(void) 72{ 73 /* endless idle loop with no priority at all */ 74 while (1) { 75 if (hlt_counter) { 76 while (!need_resched()) 77 cpu_relax(); 78 } else { 79 local_irq_disable(); 80 while (!need_resched()) { 81 local_irq_enable(); 82 hlt(); 83 local_irq_disable(); 84 } 85 local_irq_enable(); 86 } 87 preempt_enable_no_resched(); 88 schedule(); 89 preempt_disable(); 90 } 91 92} 93 94void machine_restart(char * __unused) 95{ 96 extern void phys_stext(void); 97 98 phys_stext(); 99} 100 101void machine_halt(void) 102{ 103 for (;;); 104} 105 106void machine_power_off(void) 107{ 108 extern void enter_deep_standby(void); 109 110 enter_deep_standby(); 111} 112 113void (*pm_power_off)(void) = machine_power_off; 114EXPORT_SYMBOL(pm_power_off); 115 116void show_regs(struct pt_regs * regs) 117{ 118 unsigned long long ah, al, bh, bl, ch, cl; 119 120 printk("\n"); 121 122 ah = (regs->pc) >> 32; 123 al = (regs->pc) & 0xffffffff; 124 bh = (regs->regs[18]) >> 32; 125 bl = (regs->regs[18]) & 0xffffffff; 126 ch = (regs->regs[15]) >> 32; 127 cl = (regs->regs[15]) & 0xffffffff; 128 printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", 129 ah, al, bh, bl, ch, cl); 130 131 ah = (regs->sr) >> 32; 132 al = (regs->sr) & 0xffffffff; 133 asm volatile ("getcon " __TEA ", %0" : "=r" (bh)); 134 asm volatile ("getcon " __TEA ", %0" : "=r" (bl)); 135 bh = (bh) >> 32; 136 bl = (bl) & 0xffffffff; 137 asm volatile ("getcon " __KCR0 ", %0" : "=r" (ch)); 138 asm volatile ("getcon " __KCR0 ", %0" : "=r" (cl)); 139 ch = (ch) >> 32; 140 cl = (cl) & 0xffffffff; 141 printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", 142 ah, al, bh, bl, ch, cl); 143 144 ah = (regs->regs[0]) >> 32; 145 al = (regs->regs[0]) & 0xffffffff; 146 bh = (regs->regs[1]) >> 32; 147 bl = (regs->regs[1]) & 0xffffffff; 148 ch = (regs->regs[2]) >> 32; 149 cl = (regs->regs[2]) & 0xffffffff; 150 printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", 151 ah, al, bh, bl, ch, cl); 152 153 ah = (regs->regs[3]) >> 32; 154 al = (regs->regs[3]) & 0xffffffff; 155 bh = (regs->regs[4]) >> 32; 156 bl = (regs->regs[4]) & 0xffffffff; 157 ch = (regs->regs[5]) >> 32; 158 cl = (regs->regs[5]) & 0xffffffff; 159 printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", 160 ah, al, bh, bl, ch, cl); 161 162 ah = (regs->regs[6]) >> 32; 163 al = (regs->regs[6]) & 0xffffffff; 164 bh = (regs->regs[7]) >> 32; 165 bl = (regs->regs[7]) & 0xffffffff; 166 ch = (regs->regs[8]) >> 32; 167 cl = (regs->regs[8]) & 0xffffffff; 168 printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", 169 ah, al, bh, bl, ch, cl); 170 171 ah = (regs->regs[9]) >> 32; 172 al = (regs->regs[9]) & 0xffffffff; 173 bh = (regs->regs[10]) >> 32; 174 bl = (regs->regs[10]) & 0xffffffff; 175 ch = (regs->regs[11]) >> 32; 176 cl = (regs->regs[11]) & 0xffffffff; 177 printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", 178 ah, al, bh, bl, ch, cl); 179 180 ah = (regs->regs[12]) >> 32; 181 al = (regs->regs[12]) & 0xffffffff; 182 bh = (regs->regs[13]) >> 32; 183 bl = (regs->regs[13]) & 0xffffffff; 184 ch = (regs->regs[14]) >> 32; 185 cl = (regs->regs[14]) & 0xffffffff; 186 printk("R12 : %08Lx%08Lx R13 : %08Lx%08Lx R14 : %08Lx%08Lx\n", 187 ah, al, bh, bl, ch, cl); 188 189 ah = (regs->regs[16]) >> 32; 190 al = (regs->regs[16]) & 0xffffffff; 191 bh = (regs->regs[17]) >> 32; 192 bl = (regs->regs[17]) & 0xffffffff; 193 ch = (regs->regs[19]) >> 32; 194 cl = (regs->regs[19]) & 0xffffffff; 195 printk("R16 : %08Lx%08Lx R17 : %08Lx%08Lx R19 : %08Lx%08Lx\n", 196 ah, al, bh, bl, ch, cl); 197 198 ah = (regs->regs[20]) >> 32; 199 al = (regs->regs[20]) & 0xffffffff; 200 bh = (regs->regs[21]) >> 32; 201 bl = (regs->regs[21]) & 0xffffffff; 202 ch = (regs->regs[22]) >> 32; 203 cl = (regs->regs[22]) & 0xffffffff; 204 printk("R20 : %08Lx%08Lx R21 : %08Lx%08Lx R22 : %08Lx%08Lx\n", 205 ah, al, bh, bl, ch, cl); 206 207 ah = (regs->regs[23]) >> 32; 208 al = (regs->regs[23]) & 0xffffffff; 209 bh = (regs->regs[24]) >> 32; 210 bl = (regs->regs[24]) & 0xffffffff; 211 ch = (regs->regs[25]) >> 32; 212 cl = (regs->regs[25]) & 0xffffffff; 213 printk("R23 : %08Lx%08Lx R24 : %08Lx%08Lx R25 : %08Lx%08Lx\n", 214 ah, al, bh, bl, ch, cl); 215 216 ah = (regs->regs[26]) >> 32; 217 al = (regs->regs[26]) & 0xffffffff; 218 bh = (regs->regs[27]) >> 32; 219 bl = (regs->regs[27]) & 0xffffffff; 220 ch = (regs->regs[28]) >> 32; 221 cl = (regs->regs[28]) & 0xffffffff; 222 printk("R26 : %08Lx%08Lx R27 : %08Lx%08Lx R28 : %08Lx%08Lx\n", 223 ah, al, bh, bl, ch, cl); 224 225 ah = (regs->regs[29]) >> 32; 226 al = (regs->regs[29]) & 0xffffffff; 227 bh = (regs->regs[30]) >> 32; 228 bl = (regs->regs[30]) & 0xffffffff; 229 ch = (regs->regs[31]) >> 32; 230 cl = (regs->regs[31]) & 0xffffffff; 231 printk("R29 : %08Lx%08Lx R30 : %08Lx%08Lx R31 : %08Lx%08Lx\n", 232 ah, al, bh, bl, ch, cl); 233 234 ah = (regs->regs[32]) >> 32; 235 al = (regs->regs[32]) & 0xffffffff; 236 bh = (regs->regs[33]) >> 32; 237 bl = (regs->regs[33]) & 0xffffffff; 238 ch = (regs->regs[34]) >> 32; 239 cl = (regs->regs[34]) & 0xffffffff; 240 printk("R32 : %08Lx%08Lx R33 : %08Lx%08Lx R34 : %08Lx%08Lx\n", 241 ah, al, bh, bl, ch, cl); 242 243 ah = (regs->regs[35]) >> 32; 244 al = (regs->regs[35]) & 0xffffffff; 245 bh = (regs->regs[36]) >> 32; 246 bl = (regs->regs[36]) & 0xffffffff; 247 ch = (regs->regs[37]) >> 32; 248 cl = (regs->regs[37]) & 0xffffffff; 249 printk("R35 : %08Lx%08Lx R36 : %08Lx%08Lx R37 : %08Lx%08Lx\n", 250 ah, al, bh, bl, ch, cl); 251 252 ah = (regs->regs[38]) >> 32; 253 al = (regs->regs[38]) & 0xffffffff; 254 bh = (regs->regs[39]) >> 32; 255 bl = (regs->regs[39]) & 0xffffffff; 256 ch = (regs->regs[40]) >> 32; 257 cl = (regs->regs[40]) & 0xffffffff; 258 printk("R38 : %08Lx%08Lx R39 : %08Lx%08Lx R40 : %08Lx%08Lx\n", 259 ah, al, bh, bl, ch, cl); 260 261 ah = (regs->regs[41]) >> 32; 262 al = (regs->regs[41]) & 0xffffffff; 263 bh = (regs->regs[42]) >> 32; 264 bl = (regs->regs[42]) & 0xffffffff; 265 ch = (regs->regs[43]) >> 32; 266 cl = (regs->regs[43]) & 0xffffffff; 267 printk("R41 : %08Lx%08Lx R42 : %08Lx%08Lx R43 : %08Lx%08Lx\n", 268 ah, al, bh, bl, ch, cl); 269 270 ah = (regs->regs[44]) >> 32; 271 al = (regs->regs[44]) & 0xffffffff; 272 bh = (regs->regs[45]) >> 32; 273 bl = (regs->regs[45]) & 0xffffffff; 274 ch = (regs->regs[46]) >> 32; 275 cl = (regs->regs[46]) & 0xffffffff; 276 printk("R44 : %08Lx%08Lx R45 : %08Lx%08Lx R46 : %08Lx%08Lx\n", 277 ah, al, bh, bl, ch, cl); 278 279 ah = (regs->regs[47]) >> 32; 280 al = (regs->regs[47]) & 0xffffffff; 281 bh = (regs->regs[48]) >> 32; 282 bl = (regs->regs[48]) & 0xffffffff; 283 ch = (regs->regs[49]) >> 32; 284 cl = (regs->regs[49]) & 0xffffffff; 285 printk("R47 : %08Lx%08Lx R48 : %08Lx%08Lx R49 : %08Lx%08Lx\n", 286 ah, al, bh, bl, ch, cl); 287 288 ah = (regs->regs[50]) >> 32; 289 al = (regs->regs[50]) & 0xffffffff; 290 bh = (regs->regs[51]) >> 32; 291 bl = (regs->regs[51]) & 0xffffffff; 292 ch = (regs->regs[52]) >> 32; 293 cl = (regs->regs[52]) & 0xffffffff; 294 printk("R50 : %08Lx%08Lx R51 : %08Lx%08Lx R52 : %08Lx%08Lx\n", 295 ah, al, bh, bl, ch, cl); 296 297 ah = (regs->regs[53]) >> 32; 298 al = (regs->regs[53]) & 0xffffffff; 299 bh = (regs->regs[54]) >> 32; 300 bl = (regs->regs[54]) & 0xffffffff; 301 ch = (regs->regs[55]) >> 32; 302 cl = (regs->regs[55]) & 0xffffffff; 303 printk("R53 : %08Lx%08Lx R54 : %08Lx%08Lx R55 : %08Lx%08Lx\n", 304 ah, al, bh, bl, ch, cl); 305 306 ah = (regs->regs[56]) >> 32; 307 al = (regs->regs[56]) & 0xffffffff; 308 bh = (regs->regs[57]) >> 32; 309 bl = (regs->regs[57]) & 0xffffffff; 310 ch = (regs->regs[58]) >> 32; 311 cl = (regs->regs[58]) & 0xffffffff; 312 printk("R56 : %08Lx%08Lx R57 : %08Lx%08Lx R58 : %08Lx%08Lx\n", 313 ah, al, bh, bl, ch, cl); 314 315 ah = (regs->regs[59]) >> 32; 316 al = (regs->regs[59]) & 0xffffffff; 317 bh = (regs->regs[60]) >> 32; 318 bl = (regs->regs[60]) & 0xffffffff; 319 ch = (regs->regs[61]) >> 32; 320 cl = (regs->regs[61]) & 0xffffffff; 321 printk("R59 : %08Lx%08Lx R60 : %08Lx%08Lx R61 : %08Lx%08Lx\n", 322 ah, al, bh, bl, ch, cl); 323 324 ah = (regs->regs[62]) >> 32; 325 al = (regs->regs[62]) & 0xffffffff; 326 bh = (regs->tregs[0]) >> 32; 327 bl = (regs->tregs[0]) & 0xffffffff; 328 ch = (regs->tregs[1]) >> 32; 329 cl = (regs->tregs[1]) & 0xffffffff; 330 printk("R62 : %08Lx%08Lx T0 : %08Lx%08Lx T1 : %08Lx%08Lx\n", 331 ah, al, bh, bl, ch, cl); 332 333 ah = (regs->tregs[2]) >> 32; 334 al = (regs->tregs[2]) & 0xffffffff; 335 bh = (regs->tregs[3]) >> 32; 336 bl = (regs->tregs[3]) & 0xffffffff; 337 ch = (regs->tregs[4]) >> 32; 338 cl = (regs->tregs[4]) & 0xffffffff; 339 printk("T2 : %08Lx%08Lx T3 : %08Lx%08Lx T4 : %08Lx%08Lx\n", 340 ah, al, bh, bl, ch, cl); 341 342 ah = (regs->tregs[5]) >> 32; 343 al = (regs->tregs[5]) & 0xffffffff; 344 bh = (regs->tregs[6]) >> 32; 345 bl = (regs->tregs[6]) & 0xffffffff; 346 ch = (regs->tregs[7]) >> 32; 347 cl = (regs->tregs[7]) & 0xffffffff; 348 printk("T5 : %08Lx%08Lx T6 : %08Lx%08Lx T7 : %08Lx%08Lx\n", 349 ah, al, bh, bl, ch, cl); 350 351 /* 352 * If we're in kernel mode, dump the stack too.. 353 */ 354 if (!user_mode(regs)) { 355 void show_stack(struct task_struct *tsk, unsigned long *sp); 356 unsigned long sp = regs->regs[15] & 0xffffffff; 357 struct task_struct *tsk = get_current(); 358 359 tsk->thread.kregs = regs; 360 361 show_stack(tsk, (unsigned long *)sp); 362 } 363} 364 365struct task_struct * alloc_task_struct(void) 366{ 367 /* Get task descriptor pages */ 368 return (struct task_struct *) 369 __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); 370} 371 372void free_task_struct(struct task_struct *p) 373{ 374 free_pages((unsigned long) p, get_order(THREAD_SIZE)); 375} 376 377/* 378 * Create a kernel thread 379 */ 380ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) 381{ 382 do_exit(fn(arg)); 383} 384 385/* 386 * This is the mechanism for creating a new kernel thread. 387 * 388 * NOTE! Only a kernel-only process(ie the swapper or direct descendants 389 * who haven't done an "execve()") should use this: it will work within 390 * a system call from a "real" process, but the process memory space will 391 * not be freed until both the parent and the child have exited. 392 */ 393int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 394{ 395 struct pt_regs regs; 396 397 memset(&regs, 0, sizeof(regs)); 398 regs.regs[2] = (unsigned long)arg; 399 regs.regs[3] = (unsigned long)fn; 400 401 regs.pc = (unsigned long)kernel_thread_helper; 402 regs.sr = (1 << 30); 403 404 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, 405 &regs, 0, NULL, NULL); 406} 407 408/* 409 * Free current thread data structures etc.. 410 */ 411void exit_thread(void) 412{ 413 /* See arch/sparc/kernel/process.c for the precedent for doing this -- RPC. 414 415 The SH-5 FPU save/restore approach relies on last_task_used_math 416 pointing to a live task_struct. When another task tries to use the 417 FPU for the 1st time, the FPUDIS trap handling (see 418 arch/sh64/kernel/fpu.c) will save the existing FPU state to the 419 FP regs field within last_task_used_math before re-loading the new 420 task's FPU state (or initialising it if the FPU has been used 421 before). So if last_task_used_math is stale, and its page has already been 422 re-allocated for another use, the consequences are rather grim. Unless we 423 null it here, there is no other path through which it would get safely 424 nulled. */ 425 426#ifdef CONFIG_SH_FPU 427 if (last_task_used_math == current) { 428 last_task_used_math = NULL; 429 } 430#endif 431} 432 433void flush_thread(void) 434{ 435 436 /* Called by fs/exec.c (flush_old_exec) to remove traces of a 437 * previously running executable. */ 438#ifdef CONFIG_SH_FPU 439 if (last_task_used_math == current) { 440 last_task_used_math = NULL; 441 } 442 /* Force FPU state to be reinitialised after exec */ 443 clear_used_math(); 444#endif 445 446 /* if we are a kernel thread, about to change to user thread, 447 * update kreg 448 */ 449 if(current->thread.kregs==&fake_swapper_regs) { 450 current->thread.kregs = 451 ((struct pt_regs *)(THREAD_SIZE + (unsigned long) current) - 1); 452 current->thread.uregs = current->thread.kregs; 453 } 454} 455 456void release_thread(struct task_struct *dead_task) 457{ 458 /* do nothing */ 459} 460 461/* Fill in the fpu structure for a core dump.. */ 462int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) 463{ 464#ifdef CONFIG_SH_FPU 465 int fpvalid; 466 struct task_struct *tsk = current; 467 468 fpvalid = !!tsk_used_math(tsk); 469 if (fpvalid) { 470 if (current == last_task_used_math) { 471 grab_fpu(); 472 fpsave(&tsk->thread.fpu.hard); 473 release_fpu(); 474 last_task_used_math = 0; 475 regs->sr |= SR_FD; 476 } 477 478 memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); 479 } 480 481 return fpvalid; 482#else 483 return 0; /* Task didn't use the fpu at all. */ 484#endif 485} 486 487asmlinkage void ret_from_fork(void); 488 489int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, 490 unsigned long unused, 491 struct task_struct *p, struct pt_regs *regs) 492{ 493 struct pt_regs *childregs; 494 unsigned long long se; /* Sign extension */ 495 496#ifdef CONFIG_SH_FPU 497 if(last_task_used_math == current) { 498 grab_fpu(); 499 fpsave(&current->thread.fpu.hard); 500 release_fpu(); 501 last_task_used_math = NULL; 502 regs->sr |= SR_FD; 503 } 504#endif 505 /* Copy from sh version */ 506 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; 507 508 *childregs = *regs; 509 510 if (user_mode(regs)) { 511 childregs->regs[15] = usp; 512 p->thread.uregs = childregs; 513 } else { 514 childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; 515 } 516 517 childregs->regs[9] = 0; /* Set return value for child */ 518 childregs->sr |= SR_FD; /* Invalidate FPU flag */ 519 520 p->thread.sp = (unsigned long) childregs; 521 p->thread.pc = (unsigned long) ret_from_fork; 522 523 /* 524 * Sign extend the edited stack. 525 * Note that thread.pc and thread.pc will stay 526 * 32-bit wide and context switch must take care 527 * of NEFF sign extension. 528 */ 529 530 se = childregs->regs[15]; 531 se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se; 532 childregs->regs[15] = se; 533 534 return 0; 535} 536 537asmlinkage int sys_fork(unsigned long r2, unsigned long r3, 538 unsigned long r4, unsigned long r5, 539 unsigned long r6, unsigned long r7, 540 struct pt_regs *pregs) 541{ 542 return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); 543} 544 545asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 546 unsigned long r4, unsigned long r5, 547 unsigned long r6, unsigned long r7, 548 struct pt_regs *pregs) 549{ 550 if (!newsp) 551 newsp = pregs->regs[15]; 552 return do_fork(clone_flags, newsp, pregs, 0, 0, 0); 553} 554 555/* 556 * This is trivial, and on the face of it looks like it 557 * could equally well be done in user mode. 558 * 559 * Not so, for quite unobvious reasons - register pressure. 560 * In user mode vfork() cannot have a stack frame, and if 561 * done by calling the "clone()" system call directly, you 562 * do not have enough call-clobbered registers to hold all 563 * the information you need. 564 */ 565asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, 566 unsigned long r4, unsigned long r5, 567 unsigned long r6, unsigned long r7, 568 struct pt_regs *pregs) 569{ 570 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); 571} 572 573/* 574 * sys_execve() executes a new program. 575 */ 576asmlinkage int sys_execve(char *ufilename, char **uargv, 577 char **uenvp, unsigned long r5, 578 unsigned long r6, unsigned long r7, 579 struct pt_regs *pregs) 580{ 581 int error; 582 char *filename; 583 584 lock_kernel(); 585 filename = getname((char __user *)ufilename); 586 error = PTR_ERR(filename); 587 if (IS_ERR(filename)) 588 goto out; 589 590 error = do_execve(filename, 591 (char __user * __user *)uargv, 592 (char __user * __user *)uenvp, 593 pregs); 594 if (error == 0) { 595 task_lock(current); 596 current->ptrace &= ~PT_DTRACE; 597 task_unlock(current); 598 } 599 putname(filename); 600out: 601 unlock_kernel(); 602 return error; 603} 604 605/* 606 * These bracket the sleeping functions.. 607 */ 608extern void interruptible_sleep_on(wait_queue_head_t *q); 609 610#define mid_sched ((unsigned long) interruptible_sleep_on) 611 612static int in_sh64_switch_to(unsigned long pc) 613{ 614 extern char __sh64_switch_to_end; 615 /* For a sleeping task, the PC is somewhere in the middle of the function, 616 so we don't have to worry about masking the LSB off */ 617 return (pc >= (unsigned long) sh64_switch_to) && 618 (pc < (unsigned long) &__sh64_switch_to_end); 619} 620 621unsigned long get_wchan(struct task_struct *p) 622{ 623 unsigned long schedule_fp; 624 unsigned long sh64_switch_to_fp; 625 unsigned long schedule_caller_pc; 626 unsigned long pc; 627 628 if (!p || p == current || p->state == TASK_RUNNING) 629 return 0; 630 631 /* 632 * The same comment as on the Alpha applies here, too ... 633 */ 634 pc = thread_saved_pc(p); 635 636#ifdef CONFIG_FRAME_POINTER 637 if (in_sh64_switch_to(pc)) { 638 sh64_switch_to_fp = (long) p->thread.sp; 639 /* r14 is saved at offset 4 in the sh64_switch_to frame */ 640 schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); 641 642 /* and the caller of 'schedule' is (currently!) saved at offset 24 643 in the frame of schedule (from disasm) */ 644 schedule_caller_pc = *(unsigned long *) (long)(schedule_fp + 24); 645 return schedule_caller_pc; 646 } 647#endif 648 return pc; 649} 650 651/* Provide a /proc/asids file that lists out the 652 ASIDs currently associated with the processes. (If the DM.PC register is 653 examined through the debug link, this shows ASID + PC. To make use of this, 654 the PID->ASID relationship needs to be known. This is primarily for 655 debugging.) 656 */ 657 658#if defined(CONFIG_SH64_PROC_ASIDS) 659#include <linux/init.h> 660#include <linux/proc_fs.h> 661 662static int 663asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) 664{ 665 int len=0; 666 struct task_struct *p; 667 read_lock(&tasklist_lock); 668 for_each_process(p) { 669 int pid = p->pid; 670 struct mm_struct *mm; 671 if (!pid) continue; 672 mm = p->mm; 673 if (mm) { 674 unsigned long asid, context; 675 context = mm->context; 676 asid = (context & 0xff); 677 len += sprintf(buf+len, "%5d : %02lx\n", pid, asid); 678 } else { 679 len += sprintf(buf+len, "%5d : (none)\n", pid); 680 } 681 } 682 read_unlock(&tasklist_lock); 683 *eof = 1; 684 return len; 685} 686 687static int __init register_proc_asids(void) 688{ 689 create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); 690 return 0; 691} 692 693__initcall(register_proc_asids); 694#endif 695