0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/elfcore.h>
0012 #include <linux/errno.h>
0013 #include <linux/module.h>
0014 #include <linux/sched.h>
0015 #include <linux/sched/debug.h>
0016 #include <linux/sched/task.h>
0017 #include <linux/sched/task_stack.h>
0018 #include <linux/kernel.h>
0019 #include <linux/mm.h>
0020 #include <linux/stddef.h>
0021 #include <linux/ptrace.h>
0022 #include <linux/user.h>
0023 #include <linux/smp.h>
0024 #include <linux/reboot.h>
0025 #include <linux/delay.h>
0026 #include <linux/pm.h>
0027 #include <linux/slab.h>
0028 #include <linux/cpu.h>
0029
0030 #include <asm/auxio.h>
0031 #include <asm/oplib.h>
0032 #include <linux/uaccess.h>
0033 #include <asm/page.h>
0034 #include <asm/delay.h>
0035 #include <asm/processor.h>
0036 #include <asm/psr.h>
0037 #include <asm/elf.h>
0038 #include <asm/prom.h>
0039 #include <asm/unistd.h>
0040 #include <asm/setup.h>
0041
0042 #include "kernel.h"
0043
0044
0045
0046
0047
0048 void (*sparc_idle)(void);
0049
0050
0051
0052
0053
0054
0055 void (*pm_power_off)(void) = machine_power_off;
0056 EXPORT_SYMBOL(pm_power_off);
0057
0058
0059
0060
0061
0062 int scons_pwroff = 1;
0063
0064 extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
0065
0066 struct task_struct *last_task_used_math = NULL;
0067 struct thread_info *current_set[NR_CPUS];
0068
0069
0070 void arch_cpu_idle(void)
0071 {
0072 if (sparc_idle)
0073 (*sparc_idle)();
0074 raw_local_irq_enable();
0075 }
0076
0077
0078 void machine_halt(void)
0079 {
0080 local_irq_enable();
0081 mdelay(8);
0082 local_irq_disable();
0083 prom_halt();
0084 panic("Halt failed!");
0085 }
0086
0087 void machine_restart(char * cmd)
0088 {
0089 char *p;
0090
0091 local_irq_enable();
0092 mdelay(8);
0093 local_irq_disable();
0094
0095 p = strchr (reboot_command, '\n');
0096 if (p) *p = 0;
0097 if (cmd)
0098 prom_reboot(cmd);
0099 if (*reboot_command)
0100 prom_reboot(reboot_command);
0101 prom_feval ("reset");
0102 panic("Reboot failed!");
0103 }
0104
0105 void machine_power_off(void)
0106 {
0107 if (auxio_power_register &&
0108 (!of_node_is_type(of_console_device, "serial") || scons_pwroff)) {
0109 u8 power_register = sbus_readb(auxio_power_register);
0110 power_register |= AUXIO_POWER_OFF;
0111 sbus_writeb(power_register, auxio_power_register);
0112 }
0113
0114 machine_halt();
0115 }
0116
0117 void show_regs(struct pt_regs *r)
0118 {
0119 struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
0120
0121 show_regs_print_info(KERN_DEFAULT);
0122
0123 printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n",
0124 r->psr, r->pc, r->npc, r->y, print_tainted());
0125 printk("PC: <%pS>\n", (void *) r->pc);
0126 printk("%%G: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0127 r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3],
0128 r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]);
0129 printk("%%O: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0130 r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11],
0131 r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]);
0132 printk("RPC: <%pS>\n", (void *) r->u_regs[15]);
0133
0134 printk("%%L: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0135 rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
0136 rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
0137 printk("%%I: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
0138 rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
0139 rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
0140 }
0141
0142
0143
0144
0145
0146 void show_stack(struct task_struct *tsk, unsigned long *_ksp, const char *loglvl)
0147 {
0148 unsigned long pc, fp;
0149 unsigned long task_base;
0150 struct reg_window32 *rw;
0151 int count = 0;
0152
0153 if (!tsk)
0154 tsk = current;
0155
0156 if (tsk == current && !_ksp)
0157 __asm__ __volatile__("mov %%fp, %0" : "=r" (_ksp));
0158
0159 task_base = (unsigned long) task_stack_page(tsk);
0160 fp = (unsigned long) _ksp;
0161 do {
0162
0163 if (fp < (task_base + sizeof(struct thread_info)) ||
0164 fp >= (task_base + (PAGE_SIZE << 1)))
0165 break;
0166 rw = (struct reg_window32 *) fp;
0167 pc = rw->ins[7];
0168 printk("%s[%08lx : ", loglvl, pc);
0169 printk("%s%pS ] ", loglvl, (void *) pc);
0170 fp = rw->ins[6];
0171 } while (++count < 16);
0172 printk("%s\n", loglvl);
0173 }
0174
0175
0176
0177
0178 void exit_thread(struct task_struct *tsk)
0179 {
0180 #ifndef CONFIG_SMP
0181 if (last_task_used_math == tsk) {
0182 #else
0183 if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {
0184 #endif
0185
0186 put_psr(get_psr() | PSR_EF);
0187 fpsave(&tsk->thread.float_regs[0], &tsk->thread.fsr,
0188 &tsk->thread.fpqueue[0], &tsk->thread.fpqdepth);
0189 #ifndef CONFIG_SMP
0190 last_task_used_math = NULL;
0191 #else
0192 clear_ti_thread_flag(task_thread_info(tsk), TIF_USEDFPU);
0193 #endif
0194 }
0195 }
0196
0197 void flush_thread(void)
0198 {
0199 current_thread_info()->w_saved = 0;
0200
0201 #ifndef CONFIG_SMP
0202 if(last_task_used_math == current) {
0203 #else
0204 if (test_thread_flag(TIF_USEDFPU)) {
0205 #endif
0206
0207 put_psr(get_psr() | PSR_EF);
0208 fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr,
0209 ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth);
0210 #ifndef CONFIG_SMP
0211 last_task_used_math = NULL;
0212 #else
0213 clear_thread_flag(TIF_USEDFPU);
0214 #endif
0215 }
0216 }
0217
0218 static inline struct sparc_stackf __user *
0219 clone_stackframe(struct sparc_stackf __user *dst,
0220 struct sparc_stackf __user *src)
0221 {
0222 unsigned long size, fp;
0223 struct sparc_stackf *tmp;
0224 struct sparc_stackf __user *sp;
0225
0226 if (get_user(tmp, &src->fp))
0227 return NULL;
0228
0229 fp = (unsigned long) tmp;
0230 size = (fp - ((unsigned long) src));
0231 fp = (unsigned long) dst;
0232 sp = (struct sparc_stackf __user *)(fp - size);
0233
0234
0235
0236
0237
0238 if (__copy_user(sp, src, size))
0239 sp = NULL;
0240 else if (put_user(fp, &sp->fp))
0241 sp = NULL;
0242
0243 return sp;
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 extern void ret_from_fork(void);
0260 extern void ret_from_kernel_thread(void);
0261
0262 int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
0263 {
0264 unsigned long clone_flags = args->flags;
0265 unsigned long sp = args->stack;
0266 unsigned long tls = args->tls;
0267 struct thread_info *ti = task_thread_info(p);
0268 struct pt_regs *childregs, *regs = current_pt_regs();
0269 char *new_stack;
0270
0271 #ifndef CONFIG_SMP
0272 if(last_task_used_math == current) {
0273 #else
0274 if (test_thread_flag(TIF_USEDFPU)) {
0275 #endif
0276 put_psr(get_psr() | PSR_EF);
0277 fpsave(&p->thread.float_regs[0], &p->thread.fsr,
0278 &p->thread.fpqueue[0], &p->thread.fpqdepth);
0279 }
0280
0281
0282
0283
0284
0285
0286
0287 new_stack = task_stack_page(p) + THREAD_SIZE;
0288 new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
0289 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
0290
0291
0292
0293
0294
0295
0296
0297
0298 ti->ksp = (unsigned long) new_stack;
0299 p->thread.kregs = childregs;
0300
0301 if (unlikely(args->fn)) {
0302 extern int nwindows;
0303 unsigned long psr;
0304 memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
0305 ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
0306 childregs->u_regs[UREG_G1] = (unsigned long) args->fn;
0307 childregs->u_regs[UREG_G2] = (unsigned long) args->fn_arg;
0308 psr = childregs->psr = get_psr();
0309 ti->kpsr = psr | PSR_PIL;
0310 ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);
0311 return 0;
0312 }
0313 memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
0314 childregs->u_regs[UREG_FP] = sp;
0315 ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
0316 ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
0317 ti->kwim = current->thread.fork_kwim;
0318
0319 if (sp != regs->u_regs[UREG_FP]) {
0320 struct sparc_stackf __user *childstack;
0321 struct sparc_stackf __user *parentstack;
0322
0323
0324
0325
0326
0327 childstack = (struct sparc_stackf __user *)
0328 (sp & ~0xfUL);
0329 parentstack = (struct sparc_stackf __user *)
0330 regs->u_regs[UREG_FP];
0331
0332 #if 0
0333 printk("clone: parent stack:\n");
0334 show_stackframe(parentstack);
0335 #endif
0336
0337 childstack = clone_stackframe(childstack, parentstack);
0338 if (!childstack)
0339 return -EFAULT;
0340
0341 #if 0
0342 printk("clone: child stack:\n");
0343 show_stackframe(childstack);
0344 #endif
0345
0346 childregs->u_regs[UREG_FP] = (unsigned long)childstack;
0347 }
0348
0349 #ifdef CONFIG_SMP
0350
0351 childregs->psr &= ~PSR_EF;
0352 clear_tsk_thread_flag(p, TIF_USEDFPU);
0353 #endif
0354
0355
0356 childregs->u_regs[UREG_I0] = current->pid;
0357 childregs->u_regs[UREG_I1] = 1;
0358
0359
0360 regs->u_regs[UREG_I1] = 0;
0361
0362 if (clone_flags & CLONE_SETTLS)
0363 childregs->u_regs[UREG_G7] = tls;
0364
0365 return 0;
0366 }
0367
0368 unsigned long __get_wchan(struct task_struct *task)
0369 {
0370 unsigned long pc, fp, bias = 0;
0371 unsigned long task_base = (unsigned long) task;
0372 unsigned long ret = 0;
0373 struct reg_window32 *rw;
0374 int count = 0;
0375
0376 fp = task_thread_info(task)->ksp + bias;
0377 do {
0378
0379 if (fp < (task_base + sizeof(struct thread_info)) ||
0380 fp >= (task_base + (2 * PAGE_SIZE)))
0381 break;
0382 rw = (struct reg_window32 *) fp;
0383 pc = rw->ins[7];
0384 if (!in_sched_functions(pc)) {
0385 ret = pc;
0386 goto out;
0387 }
0388 fp = rw->ins[6] + bias;
0389 } while (++count < 16);
0390
0391 out:
0392 return ret;
0393 }
0394