16496a23add642b7c9203411bdff3ff761835a80aMichal Simek/* 26496a23add642b7c9203411bdff3ff761835a80aMichal Simek * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 36496a23add642b7c9203411bdff3ff761835a80aMichal Simek * Copyright (C) 2008-2009 PetaLogix 46496a23add642b7c9203411bdff3ff761835a80aMichal Simek * Copyright (C) 2006 Atmark Techno, Inc. 56496a23add642b7c9203411bdff3ff761835a80aMichal Simek * 66496a23add642b7c9203411bdff3ff761835a80aMichal Simek * This file is subject to the terms and conditions of the GNU General Public 76496a23add642b7c9203411bdff3ff761835a80aMichal Simek * License. See the file "COPYING" in the main directory of this archive 86496a23add642b7c9203411bdff3ff761835a80aMichal Simek * for more details. 96496a23add642b7c9203411bdff3ff761835a80aMichal Simek */ 106496a23add642b7c9203411bdff3ff761835a80aMichal Simek 11579907e622067b13f8c6134c1b311664e77743b5Michal Simek#include <linux/cpu.h> 12d64af918feb6cb81c396d6d2dabb738bc51dda3fMichal Simek#include <linux/export.h> 136496a23add642b7c9203411bdff3ff761835a80aMichal Simek#include <linux/sched.h> 146496a23add642b7c9203411bdff3ff761835a80aMichal Simek#include <linux/pm.h> 156496a23add642b7c9203411bdff3ff761835a80aMichal Simek#include <linux/tick.h> 166496a23add642b7c9203411bdff3ff761835a80aMichal Simek#include <linux/bitops.h> 17f3268edbe6fe0ce56e62c6d6b14640aeb04864b7Al Viro#include <linux/ptrace.h> 186496a23add642b7c9203411bdff3ff761835a80aMichal Simek#include <asm/pgalloc.h> 196bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek#include <linux/uaccess.h> /* for USER_DS macros */ 20a1f55113ca2130f775eeebe799a401619bfd0295Michal Simek#include <asm/cacheflush.h> 216496a23add642b7c9203411bdff3ff761835a80aMichal Simek 226496a23add642b7c9203411bdff3ff761835a80aMichal Simekvoid show_regs(struct pt_regs *regs) 236496a23add642b7c9203411bdff3ff761835a80aMichal Simek{ 24a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo show_regs_print_info(KERN_INFO); 25a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo 266bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" Registers dump: mode=%X\r\n", regs->pt_mode); 276bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n", 286496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r1, regs->r2, regs->r3, regs->r4); 296bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n", 306496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r5, regs->r6, regs->r7, regs->r8); 316bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r9=%08lX, r10=%08lX, r11=%08lX, r12=%08lX\n", 326496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r9, regs->r10, regs->r11, regs->r12); 336bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r13=%08lX, r14=%08lX, r15=%08lX, r16=%08lX\n", 346496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r13, regs->r14, regs->r15, regs->r16); 356bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r17=%08lX, r18=%08lX, r19=%08lX, r20=%08lX\n", 366496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r17, regs->r18, regs->r19, regs->r20); 376bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r21=%08lX, r22=%08lX, r23=%08lX, r24=%08lX\n", 386496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r21, regs->r22, regs->r23, regs->r24); 396bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r25=%08lX, r26=%08lX, r27=%08lX, r28=%08lX\n", 406496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r25, regs->r26, regs->r27, regs->r28); 416bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" r29=%08lX, r30=%08lX, r31=%08lX, rPC=%08lX\n", 426496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->r29, regs->r30, regs->r31, regs->pc); 436bd55f0bbaebb79b39e147aa864401fd0c94db82Michal Simek pr_info(" msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n", 446496a23add642b7c9203411bdff3ff761835a80aMichal Simek regs->msr, regs->ear, regs->esr, regs->fsr); 456496a23add642b7c9203411bdff3ff761835a80aMichal Simek} 466496a23add642b7c9203411bdff3ff761835a80aMichal Simek 476496a23add642b7c9203411bdff3ff761835a80aMichal Simekvoid (*pm_power_off)(void) = NULL; 486496a23add642b7c9203411bdff3ff761835a80aMichal SimekEXPORT_SYMBOL(pm_power_off); 496496a23add642b7c9203411bdff3ff761835a80aMichal Simek 506496a23add642b7c9203411bdff3ff761835a80aMichal Simekvoid flush_thread(void) 516496a23add642b7c9203411bdff3ff761835a80aMichal Simek{ 526496a23add642b7c9203411bdff3ff761835a80aMichal Simek} 536496a23add642b7c9203411bdff3ff761835a80aMichal Simek 54a8fb748e89957426fafb2e2efccd5ce635d6f530Michal Simekint copy_thread(unsigned long clone_flags, unsigned long usp, 55afa86fc426ff7e7f5477f15da9c405d08d5cf790Al Viro unsigned long arg, struct task_struct *p) 566496a23add642b7c9203411bdff3ff761835a80aMichal Simek{ 576496a23add642b7c9203411bdff3ff761835a80aMichal Simek struct pt_regs *childregs = task_pt_regs(p); 586496a23add642b7c9203411bdff3ff761835a80aMichal Simek struct thread_info *ti = task_thread_info(p); 596496a23add642b7c9203411bdff3ff761835a80aMichal Simek 602319295dd8dbd076afa136bffb797ef726b605a0Al Viro if (unlikely(p->flags & PF_KTHREAD)) { 612319295dd8dbd076afa136bffb797ef726b605a0Al Viro /* if we're creating a new kernel thread then just zeroing all 622319295dd8dbd076afa136bffb797ef726b605a0Al Viro * the registers. That's OK for a brand new thread.*/ 632319295dd8dbd076afa136bffb797ef726b605a0Al Viro memset(childregs, 0, sizeof(struct pt_regs)); 642319295dd8dbd076afa136bffb797ef726b605a0Al Viro memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 652319295dd8dbd076afa136bffb797ef726b605a0Al Viro ti->cpu_context.r1 = (unsigned long)childregs; 662319295dd8dbd076afa136bffb797ef726b605a0Al Viro ti->cpu_context.r20 = (unsigned long)usp; /* fn */ 672319295dd8dbd076afa136bffb797ef726b605a0Al Viro ti->cpu_context.r19 = (unsigned long)arg; 682319295dd8dbd076afa136bffb797ef726b605a0Al Viro childregs->pt_mode = 1; 692319295dd8dbd076afa136bffb797ef726b605a0Al Viro local_save_flags(childregs->msr); 702319295dd8dbd076afa136bffb797ef726b605a0Al Viro#ifdef CONFIG_MMU 712319295dd8dbd076afa136bffb797ef726b605a0Al Viro ti->cpu_context.msr = childregs->msr & ~MSR_IE; 722319295dd8dbd076afa136bffb797ef726b605a0Al Viro#endif 732319295dd8dbd076afa136bffb797ef726b605a0Al Viro ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; 742319295dd8dbd076afa136bffb797ef726b605a0Al Viro return 0; 752319295dd8dbd076afa136bffb797ef726b605a0Al Viro } 76f3268edbe6fe0ce56e62c6d6b14640aeb04864b7Al Viro *childregs = *current_pt_regs(); 77f3268edbe6fe0ce56e62c6d6b14640aeb04864b7Al Viro if (usp) 78f3268edbe6fe0ce56e62c6d6b14640aeb04864b7Al Viro childregs->r1 = usp; 796496a23add642b7c9203411bdff3ff761835a80aMichal Simek 806496a23add642b7c9203411bdff3ff761835a80aMichal Simek memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 816496a23add642b7c9203411bdff3ff761835a80aMichal Simek ti->cpu_context.r1 = (unsigned long)childregs; 822319295dd8dbd076afa136bffb797ef726b605a0Al Viro#ifndef CONFIG_MMU 836496a23add642b7c9203411bdff3ff761835a80aMichal Simek ti->cpu_context.msr = (unsigned long)childregs->msr; 845233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#else 852319295dd8dbd076afa136bffb797ef726b605a0Al Viro childregs->msr |= MSR_UMS; 865233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek 875233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek /* we should consider the fact that childregs is a copy of the parent 885233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * regs which were saved immediately after entering the kernel state 895233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * before enabling VM. This MSR will be restored in switch_to and 905233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * RETURN() and we want to have the right machine state there 915233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * specifically this state must have INTs disabled before and enabled 925233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * after performing rtbd 935233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * compose the right MSR for RETURN(). It will work for switch_to also 945233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * excepting for VM and UMS 955233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * don't touch UMS , CARRY and cache bits 965233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * right now MSR is a copy of parent one */ 975233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek childregs->msr &= ~MSR_EIP; 985233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek childregs->msr |= MSR_IE; 995233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek childregs->msr &= ~MSR_VM; 1005233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek childregs->msr |= MSR_VMS; 1015233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek childregs->msr |= MSR_EE; /* exceptions will be enabled*/ 1025233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek 1035233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek ti->cpu_context.msr = (childregs->msr|MSR_VM); 1045233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek ti->cpu_context.msr &= ~MSR_UMS; /* switch_to to kernel mode */ 10584ac218f0257a0cfd7689d9a44f53118dbf307b3Peter Zijlstra ti->cpu_context.msr &= ~MSR_IE; 1065233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#endif 1076496a23add642b7c9203411bdff3ff761835a80aMichal Simek ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8; 1086496a23add642b7c9203411bdff3ff761835a80aMichal Simek 109d5c15f17844b8883bc13b61a8ae114f0d3d59cddEdgar E. Iglesias /* 110d5c15f17844b8883bc13b61a8ae114f0d3d59cddEdgar E. Iglesias * r21 is the thread reg, r10 is 6th arg to clone 111d5c15f17844b8883bc13b61a8ae114f0d3d59cddEdgar E. Iglesias * which contains TLS area 112d5c15f17844b8883bc13b61a8ae114f0d3d59cddEdgar E. Iglesias */ 1136496a23add642b7c9203411bdff3ff761835a80aMichal Simek if (clone_flags & CLONE_SETTLS) 114d5c15f17844b8883bc13b61a8ae114f0d3d59cddEdgar E. Iglesias childregs->r21 = childregs->r10; 1156496a23add642b7c9203411bdff3ff761835a80aMichal Simek 1166496a23add642b7c9203411bdff3ff761835a80aMichal Simek return 0; 1176496a23add642b7c9203411bdff3ff761835a80aMichal Simek} 1186496a23add642b7c9203411bdff3ff761835a80aMichal Simek 1195233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#ifndef CONFIG_MMU 1206496a23add642b7c9203411bdff3ff761835a80aMichal Simek/* 1216496a23add642b7c9203411bdff3ff761835a80aMichal Simek * Return saved PC of a blocked thread. 1226496a23add642b7c9203411bdff3ff761835a80aMichal Simek */ 1236496a23add642b7c9203411bdff3ff761835a80aMichal Simekunsigned long thread_saved_pc(struct task_struct *tsk) 1246496a23add642b7c9203411bdff3ff761835a80aMichal Simek{ 1256496a23add642b7c9203411bdff3ff761835a80aMichal Simek struct cpu_context *ctx = 1266496a23add642b7c9203411bdff3ff761835a80aMichal Simek &(((struct thread_info *)(tsk->stack))->cpu_context); 1276496a23add642b7c9203411bdff3ff761835a80aMichal Simek 1286496a23add642b7c9203411bdff3ff761835a80aMichal Simek /* Check whether the thread is blocked in resume() */ 1296496a23add642b7c9203411bdff3ff761835a80aMichal Simek if (in_sched_functions(ctx->r15)) 1306496a23add642b7c9203411bdff3ff761835a80aMichal Simek return (unsigned long)ctx->r15; 1316496a23add642b7c9203411bdff3ff761835a80aMichal Simek else 1326496a23add642b7c9203411bdff3ff761835a80aMichal Simek return ctx->r14; 1336496a23add642b7c9203411bdff3ff761835a80aMichal Simek} 1345233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#endif 1356496a23add642b7c9203411bdff3ff761835a80aMichal Simek 1366496a23add642b7c9203411bdff3ff761835a80aMichal Simekunsigned long get_wchan(struct task_struct *p) 1376496a23add642b7c9203411bdff3ff761835a80aMichal Simek{ 1386496a23add642b7c9203411bdff3ff761835a80aMichal Simek/* TBD (used by procfs) */ 1396496a23add642b7c9203411bdff3ff761835a80aMichal Simek return 0; 1406496a23add642b7c9203411bdff3ff761835a80aMichal Simek} 141e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek 142e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek/* Set up a thread for executing a new program */ 143e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simekvoid start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) 144e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek{ 145e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek regs->pc = pc; 146e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek regs->r1 = usp; 147e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek regs->pt_mode = 0; 148f1ae3f6918ee4a437b4166a4deab4bd79629bc09Michal Simek#ifdef CONFIG_MMU 149866d72295d52353eeb0c36ccd8e5813dca869265John Williams regs->msr |= MSR_UMS; 15099c59f60fd751876c37fbea01e55606441ac6db4Al Viro regs->msr &= ~MSR_VM; 151f1ae3f6918ee4a437b4166a4deab4bd79629bc09Michal Simek#endif 152e1c4bd0897b6d03eff4b32197d6ab017f83fc836Michal Simek} 1535233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek 1545233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#ifdef CONFIG_MMU 1555233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#include <linux/elfcore.h> 1565233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek/* 1575233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek * Set up a thread for executing a new program 1585233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek */ 1595233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simekint dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) 1605233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek{ 1615233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek return 0; /* MicroBlaze has no separate FPU registers */ 1625233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek} 1635233806dfe6f88fb1a01db3729eeda78f65bcbd1Michal Simek#endif /* CONFIG_MMU */ 164a047775e7eff511a529bf65f3b3e9c11443789b2Michal Simek 165a047775e7eff511a529bf65f3b3e9c11443789b2Michal Simekvoid arch_cpu_idle(void) 166a047775e7eff511a529bf65f3b3e9c11443789b2Michal Simek{ 167a047775e7eff511a529bf65f3b3e9c11443789b2Michal Simek local_irq_enable(); 168a047775e7eff511a529bf65f3b3e9c11443789b2Michal Simek} 169