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