Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7 *
  8 * Vineetg: Aug 2009
  9 *  -"C" version of lowest level context switch asm macro called by schedular
 10 *   gcc doesn't generate the dward CFI info for hand written asm, hence can't
 11 *   backtrace out of it (e.g. tasks sleeping in kernel).
 12 *   So we cheat a bit by writing almost similar code in inline-asm.
 13 *  -This is a hacky way of doing things, but there is no other simple way.
 14 *   I don't want/intend to extend unwinding code to understand raw asm
 15 */
 16
 17#include <asm/asm-offsets.h>
 18#include <linux/sched.h>
 19#include <linux/sched/debug.h>
 20#ifdef CONFIG_ARC_PLAT_EZNPS
 21#include <plat/ctop.h>
 22#endif
 23
 24#define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
 25
 26struct task_struct *__sched
 27__switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 28{
 29	unsigned int tmp;
 30	unsigned int prev = (unsigned int)prev_task;
 31	unsigned int next = (unsigned int)next_task;
 32
 33	__asm__ __volatile__(
 34		/* FP/BLINK save generated by gcc (standard function prologue */
 35		"st.a    r13, [sp, -4]   \n\t"
 36		"st.a    r14, [sp, -4]   \n\t"
 37		"st.a    r15, [sp, -4]   \n\t"
 38		"st.a    r16, [sp, -4]   \n\t"
 39		"st.a    r17, [sp, -4]   \n\t"
 40		"st.a    r18, [sp, -4]   \n\t"
 41		"st.a    r19, [sp, -4]   \n\t"
 42		"st.a    r20, [sp, -4]   \n\t"
 43		"st.a    r21, [sp, -4]   \n\t"
 44		"st.a    r22, [sp, -4]   \n\t"
 45		"st.a    r23, [sp, -4]   \n\t"
 46		"st.a    r24, [sp, -4]   \n\t"
 47#ifndef CONFIG_ARC_CURR_IN_REG
 48		"st.a    r25, [sp, -4]   \n\t"
 49#else
 50		"sub     sp, sp, 4      \n\t"	/* usual r25 placeholder */
 51#endif
 52
 53		/* set ksp of outgoing task in tsk->thread.ksp */
 54#if KSP_WORD_OFF <= 255
 55		"st.as   sp, [%3, %1]    \n\t"
 56#else
 57		/*
 58		 * Workaround for NR_CPUS=4k
 59		 * %1 is bigger than 255 (S9 offset for st.as)
 60		 */
 61		"add2    r24, %3, %1     \n\t"
 62		"st      sp, [r24]       \n\t"
 63#endif
 64
 65		/*
 66		 * setup _current_task with incoming tsk.
 67		 * optionally, set r25 to that as well
 68		 * For SMP extra work to get to &_current_task[cpu]
 69		 * (open coded SET_CURR_TASK_ON_CPU)
 70		 */
 71#ifndef CONFIG_SMP
 72		"st  %2, [@_current_task]	\n\t"
 73#else
 74#ifdef CONFIG_ARC_PLAT_EZNPS
 75		"lr   r24, [%4]		\n\t"
 76#ifndef CONFIG_EZNPS_MTM_EXT
 77		"lsr  r24, r24, 4		\n\t"
 78#endif
 79#else
 80		"lr   r24, [identity]		\n\t"
 81		"lsr  r24, r24, 8		\n\t"
 82		"bmsk r24, r24, 7		\n\t"
 83#endif
 84		"add2 r24, @_current_task, r24	\n\t"
 85		"st   %2,  [r24]		\n\t"
 86#endif
 87#ifdef CONFIG_ARC_CURR_IN_REG
 88		"mov r25, %2   \n\t"
 89#endif
 90
 91		/* get ksp of incoming task from tsk->thread.ksp */
 92		"ld.as  sp, [%2, %1]   \n\t"
 93
 94		/* start loading it's CALLEE reg file */
 95
 96#ifndef CONFIG_ARC_CURR_IN_REG
 97		"ld.ab   r25, [sp, 4]   \n\t"
 98#else
 99		"add    sp, sp, 4       \n\t"
100#endif
101		"ld.ab   r24, [sp, 4]   \n\t"
102		"ld.ab   r23, [sp, 4]   \n\t"
103		"ld.ab   r22, [sp, 4]   \n\t"
104		"ld.ab   r21, [sp, 4]   \n\t"
105		"ld.ab   r20, [sp, 4]   \n\t"
106		"ld.ab   r19, [sp, 4]   \n\t"
107		"ld.ab   r18, [sp, 4]   \n\t"
108		"ld.ab   r17, [sp, 4]   \n\t"
109		"ld.ab   r16, [sp, 4]   \n\t"
110		"ld.ab   r15, [sp, 4]   \n\t"
111		"ld.ab   r14, [sp, 4]   \n\t"
112		"ld.ab   r13, [sp, 4]   \n\t"
113
114		/* last (ret value) = prev : although for ARC it mov r0, r0 */
115		"mov     %0, %3        \n\t"
116
117		/* FP/BLINK restore generated by gcc (standard func epilogue */
118
119		: "=r"(tmp)
120		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
121#ifdef CONFIG_ARC_PLAT_EZNPS
122		, "i"(CTOP_AUX_LOGIC_GLOBAL_ID)
123#endif
124		: "blink"
125	);
126
127	return (struct task_struct *)tmp;
128}