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 * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. 7 * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org) 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 9 * Copyright (C) 2004 Thiemo Seufer 10 */ 11 #include <linux/config.h> 12 #include <linux/errno.h> 13 #include <linux/module.h> 14 #include <linux/sched.h> 15 #include <linux/kernel.h> 16 #include <linux/mm.h> 17 #include <linux/stddef.h> 18 #include <linux/unistd.h> 19 #include <linux/ptrace.h> 20 #include <linux/slab.h> 21 #include <linux/mman.h> 22 #include <linux/personality.h> 23 #include <linux/sys.h> 24 #include <linux/user.h> 25 #include <linux/a.out.h> 26 #include <linux/init.h> 27 #include <linux/completion.h> 28 #include <linux/kallsyms.h> 29 30 #include <asm/abi.h> 31 #include <asm/bootinfo.h> 32 #include <asm/cpu.h> 33 #include <asm/dsp.h> 34 #include <asm/fpu.h> 35 #include <asm/pgtable.h> 36 #include <asm/system.h> 37 #include <asm/mipsregs.h> 38 #include <asm/processor.h> 39 #include <asm/uaccess.h> 40 #include <asm/io.h> 41 #include <asm/elf.h> 42 #include <asm/isadep.h> 43 #include <asm/inst.h> 44 45 /* 46 * The idle thread. There's no useful work to be done, so just try to conserve 47 * power and have a low exit latency (ie sit in a loop waiting for somebody to 48 * say that they'd like to reschedule) 49 */ 50 ATTRIB_NORET void cpu_idle(void) 51 { 52 /* endless idle loop with no priority at all */ 53 while (1) { 54 while (!need_resched()) 55 if (cpu_wait) 56 (*cpu_wait)(); 57 preempt_enable_no_resched(); 58 schedule(); 59 preempt_disable(); 60 } 61 } 62 63 /* 64 * Native o32 and N64 ABI without DSP ASE 65 */ 66 struct mips_abi mips_abi = { 67 .do_signal = do_signal, 68 #ifdef CONFIG_TRAD_SIGNALS 69 .setup_frame = setup_frame, 70 #endif 71 .setup_rt_frame = setup_rt_frame 72 }; 73 74 #ifdef CONFIG_MIPS32_O32 75 /* 76 * o32 compatibility on 64-bit kernels, without DSP ASE 77 */ 78 struct mips_abi mips_abi_32 = { 79 .do_signal = do_signal32, 80 .setup_frame = setup_frame_32, 81 .setup_rt_frame = setup_rt_frame_32 82 }; 83 #endif /* CONFIG_MIPS32_O32 */ 84 85 #ifdef CONFIG_MIPS32_N32 86 /* 87 * N32 on 64-bit kernels, without DSP ASE 88 */ 89 struct mips_abi mips_abi_n32 = { 90 .do_signal = do_signal, 91 .setup_rt_frame = setup_rt_frame_n32 92 }; 93 #endif /* CONFIG_MIPS32_N32 */ 94 95 asmlinkage void ret_from_fork(void); 96 97 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) 98 { 99 unsigned long status; 100 101 /* New thread loses kernel privileges. */ 102 status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|KU_MASK); 103 #ifdef CONFIG_64BIT 104 status &= ~ST0_FR; 105 status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR; 106 #endif 107 status |= KU_USER; 108 regs->cp0_status = status; 109 clear_used_math(); 110 lose_fpu(); 111 if (cpu_has_dsp) 112 __init_dsp(); 113 regs->cp0_epc = pc; 114 regs->regs[29] = sp; 115 current_thread_info()->addr_limit = USER_DS; 116 } 117 118 void exit_thread(void) 119 { 120 } 121 122 void flush_thread(void) 123 { 124 } 125 126 int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, 127 unsigned long unused, struct task_struct *p, struct pt_regs *regs) 128 { 129 struct thread_info *ti = task_thread_info(p); 130 struct pt_regs *childregs; 131 long childksp; 132 p->set_child_tid = p->clear_child_tid = NULL; 133 134 childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; 135 136 preempt_disable(); 137 138 if (is_fpu_owner()) 139 save_fp(p); 140 141 if (cpu_has_dsp) 142 save_dsp(p); 143 144 preempt_enable(); 145 146 /* set up new TSS. */ 147 childregs = (struct pt_regs *) childksp - 1; 148 *childregs = *regs; 149 childregs->regs[7] = 0; /* Clear error flag */ 150 151 #if defined(CONFIG_BINFMT_IRIX) 152 if (current->personality != PER_LINUX) { 153 /* Under IRIX things are a little different. */ 154 childregs->regs[3] = 1; 155 regs->regs[3] = 0; 156 } 157 #endif 158 childregs->regs[2] = 0; /* Child gets zero as return value */ 159 regs->regs[2] = p->pid; 160 161 if (childregs->cp0_status & ST0_CU0) { 162 childregs->regs[28] = (unsigned long) ti; 163 childregs->regs[29] = childksp; 164 ti->addr_limit = KERNEL_DS; 165 } else { 166 childregs->regs[29] = usp; 167 ti->addr_limit = USER_DS; 168 } 169 p->thread.reg29 = (unsigned long) childregs; 170 p->thread.reg31 = (unsigned long) ret_from_fork; 171 172 /* 173 * New tasks lose permission to use the fpu. This accelerates context 174 * switching for most programs since they don't use the fpu. 175 */ 176 p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); 177 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); 178 clear_tsk_thread_flag(p, TIF_USEDFPU); 179 180 if (clone_flags & CLONE_SETTLS) 181 ti->tp_value = regs->regs[7]; 182 183 return 0; 184 } 185 186 /* Fill in the fpu structure for a core dump.. */ 187 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) 188 { 189 memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); 190 191 return 1; 192 } 193 194 void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs) 195 { 196 int i; 197 198 for (i = 0; i < EF_R0; i++) 199 gp[i] = 0; 200 gp[EF_R0] = 0; 201 for (i = 1; i <= 31; i++) 202 gp[EF_R0 + i] = regs->regs[i]; 203 gp[EF_R26] = 0; 204 gp[EF_R27] = 0; 205 gp[EF_LO] = regs->lo; 206 gp[EF_HI] = regs->hi; 207 gp[EF_CP0_EPC] = regs->cp0_epc; 208 gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr; 209 gp[EF_CP0_STATUS] = regs->cp0_status; 210 gp[EF_CP0_CAUSE] = regs->cp0_cause; 211 #ifdef EF_UNUSED0 212 gp[EF_UNUSED0] = 0; 213 #endif 214 } 215 216 int dump_task_regs (struct task_struct *tsk, elf_gregset_t *regs) 217 { 218 elf_dump_regs(*regs, task_pt_regs(tsk)); 219 return 1; 220 } 221 222 int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr) 223 { 224 memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu)); 225 226 return 1; 227 } 228 229 /* 230 * Create a kernel thread 231 */ 232 ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) 233 { 234 do_exit(fn(arg)); 235 } 236 237 long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 238 { 239 struct pt_regs regs; 240 241 memset(®s, 0, sizeof(regs)); 242 243 regs.regs[4] = (unsigned long) arg; 244 regs.regs[5] = (unsigned long) fn; 245 regs.cp0_epc = (unsigned long) kernel_thread_helper; 246 regs.cp0_status = read_c0_status(); 247 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 248 regs.cp0_status &= ~(ST0_KUP | ST0_IEC); 249 regs.cp0_status |= ST0_IEP; 250 #else 251 regs.cp0_status |= ST0_EXL; 252 #endif 253 254 /* Ok, create the new process.. */ 255 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); 256 } 257 258 static struct mips_frame_info { 259 void *func; 260 unsigned long func_size; 261 int frame_size; 262 int pc_offset; 263 } *schedule_frame, mfinfo[64]; 264 static int mfinfo_num; 265 266 static int __init get_frame_info(struct mips_frame_info *info) 267 { 268 int i; 269 void *func = info->func; 270 union mips_instruction *ip = (union mips_instruction *)func; 271 info->pc_offset = -1; 272 info->frame_size = 0; 273 for (i = 0; i < 128; i++, ip++) { 274 /* if jal, jalr, jr, stop. */ 275 if (ip->j_format.opcode == jal_op || 276 (ip->r_format.opcode == spec_op && 277 (ip->r_format.func == jalr_op || 278 ip->r_format.func == jr_op))) 279 break; 280 281 if (info->func_size && i >= info->func_size / 4) 282 break; 283 if ( 284 #ifdef CONFIG_32BIT 285 ip->i_format.opcode == addiu_op && 286 #endif 287 #ifdef CONFIG_64BIT 288 ip->i_format.opcode == daddiu_op && 289 #endif 290 ip->i_format.rs == 29 && 291 ip->i_format.rt == 29) { 292 /* addiu/daddiu sp,sp,-imm */ 293 if (info->frame_size) 294 continue; 295 info->frame_size = - ip->i_format.simmediate; 296 } 297 298 if ( 299 #ifdef CONFIG_32BIT 300 ip->i_format.opcode == sw_op && 301 #endif 302 #ifdef CONFIG_64BIT 303 ip->i_format.opcode == sd_op && 304 #endif 305 ip->i_format.rs == 29 && 306 ip->i_format.rt == 31) { 307 /* sw / sd $ra, offset($sp) */ 308 if (info->pc_offset != -1) 309 continue; 310 info->pc_offset = 311 ip->i_format.simmediate / sizeof(long); 312 } 313 } 314 if (info->pc_offset == -1 || info->frame_size == 0) { 315 if (func == schedule) 316 printk("Can't analyze prologue code at %p\n", func); 317 info->pc_offset = -1; 318 info->frame_size = 0; 319 } 320 321 return 0; 322 } 323 324 static int __init frame_info_init(void) 325 { 326 int i; 327 #ifdef CONFIG_KALLSYMS 328 char *modname; 329 char namebuf[KSYM_NAME_LEN + 1]; 330 unsigned long start, size, ofs; 331 extern char __sched_text_start[], __sched_text_end[]; 332 extern char __lock_text_start[], __lock_text_end[]; 333 334 start = (unsigned long)__sched_text_start; 335 for (i = 0; i < ARRAY_SIZE(mfinfo); i++) { 336 if (start == (unsigned long)schedule) 337 schedule_frame = &mfinfo[i]; 338 if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf)) 339 break; 340 mfinfo[i].func = (void *)(start + ofs); 341 mfinfo[i].func_size = size; 342 start += size - ofs; 343 if (start >= (unsigned long)__lock_text_end) 344 break; 345 if (start == (unsigned long)__sched_text_end) 346 start = (unsigned long)__lock_text_start; 347 } 348 #else 349 mfinfo[0].func = schedule; 350 schedule_frame = &mfinfo[0]; 351 #endif 352 for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++) 353 get_frame_info(&mfinfo[i]); 354 355 mfinfo_num = i; 356 return 0; 357 } 358 359 arch_initcall(frame_info_init); 360 361 /* 362 * Return saved PC of a blocked thread. 363 */ 364 unsigned long thread_saved_pc(struct task_struct *tsk) 365 { 366 struct thread_struct *t = &tsk->thread; 367 368 /* New born processes are a special case */ 369 if (t->reg31 == (unsigned long) ret_from_fork) 370 return t->reg31; 371 372 if (!schedule_frame || schedule_frame->pc_offset < 0) 373 return 0; 374 return ((unsigned long *)t->reg29)[schedule_frame->pc_offset]; 375 } 376 377 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */ 378 unsigned long get_wchan(struct task_struct *p) 379 { 380 unsigned long stack_page; 381 unsigned long pc; 382 #ifdef CONFIG_KALLSYMS 383 unsigned long frame; 384 #endif 385 386 if (!p || p == current || p->state == TASK_RUNNING) 387 return 0; 388 389 stack_page = (unsigned long)task_stack_page(p); 390 if (!stack_page || !mfinfo_num) 391 return 0; 392 393 pc = thread_saved_pc(p); 394 #ifdef CONFIG_KALLSYMS 395 if (!in_sched_functions(pc)) 396 return pc; 397 398 frame = p->thread.reg29 + schedule_frame->frame_size; 399 do { 400 int i; 401 402 if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32) 403 return 0; 404 405 for (i = mfinfo_num - 1; i >= 0; i--) { 406 if (pc >= (unsigned long) mfinfo[i].func) 407 break; 408 } 409 if (i < 0) 410 break; 411 412 pc = ((unsigned long *)frame)[mfinfo[i].pc_offset]; 413 if (!mfinfo[i].frame_size) 414 break; 415 frame += mfinfo[i].frame_size; 416 } while (in_sched_functions(pc)); 417 #endif 418 419 return pc; 420 } 421 422