cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ctx_sw.c (3210B)


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